AngularJS and Shopify

New Member
3 0 5

I would like for this thread to serve as a useful resource for people interested in using AngularJS as part of their Shopify front-end. So far, this has proven to be much more difficult to achieve than using a library like jQuery.

I have recently begun the process of implementing a "product customizer" feature that is powered by AngularJS. It basically allows users to customize a product by attaching line item properties to their cart product (say consumers want a custom-generated image printed onto their product).

Anyway, I am going to start with the very basics of what needs to be done to get up and running with Angular in Shopify.

1. Avoid templating conflicts between AngularJS and Liquid.

Change Angular's templating interpolation from: 

{{ }}

to something like:

{[{ }]}

You can change it in Angular via the $interpolateProvider, like so:

angular.module('myApp', []).config(function ($interpolateProvider) {
  $interpolateProvider.startSymbol('{[{').endSymbol('}]}');
});

2. Referencing Angular templates/views can be tricky.

Due to the way Shopify structures its assets folder/CDN, you cannot simply specify Angular routes to use a templateUrl like `/views/your-view.html`. This is because: (1) Shopify does not allow subfolders to exist at all in the assets folder (booo), and (2) even if it did, Angular still thinks the specified view is at the base URL, like: `your-shopify.com/views/your-view.html`, when in reality, Shopify moves all the assets/referents to the CDN.

This is overcome simply by using Liquid interpolated inside the application's JavaScript (see the value provided for `templateUrl`). Since folders are not allowed, it can be helpful to follow a file naming convention such as myapp-view-{viewname}.liquid:

angular.module('myApp', ['ngRoute']).config(function ($routeProvider) {
    $routeProvider
      .when('/', {
        controller: 'MainCtrl',
        templateUrl: "{{ 'myapp-view-main.liquid' | asset_url }}"
      })
      .when('/about', {
        controller: 'AboutCtrl',
        templateUrl: "{{ 'myapp-view-about.liquid' | asset_url }}"
      })
      .otherwise({
        redirectTo: '/'
    });
});

angular.module('myApp')
  .controller('AboutCtrl', function ($scope) {
    $scope.hi = 'Hello!'
});

angular.module('myApp')
  .controller('MainCtrl', function ($scope) {
    $scope.hi = 'Hola!'
});

Although you're now correctly referencing the views, Angular is going to block the loading of a resource from any untrusted source:

Blocked loading resource from url not allowed by $sceDelegate policy.  URL: //cdn.shopify.com/s/files/1/9393/8282/t/2/assets/your-view.liquid?1459

To overcome this, you either have to whitelist the assets URI, or disable Angular's sceProvider like so:

angular.module('myApp', []).config(function ($sceProvider) {
  $sceProvider.enabled(false);
});

I am going to leave it at this for now. Does anyone else have experience using Angular and Shopify together? I would love to hear your thoughts.

Potentially helpful resources:

http://docs.shopify.com/support/your-website/themes/can-i-use-ajax-api#add-to-cart

http://docs.shopify.com/support/your-store/products/how-do-I-collect-additional-information-on-the-p...

5 Likes
Highlighted
Shopify Partner
14 0 1

I am relatively new to both Shopify and to Angular.js so maybe this is obvious to the more experienced.  I found it very useful to pass a Shopify "product" object directly to my Angular module so that it could be used by the controllers.  Shopify supports output to json for some "objects."  Angular supports passing a value to the Angular module.  Put it together and you can pass the Shopify json representation of the object to your controller.  This reduces the need for Shopify template variables because the information can be accessed through the the controller.

A liquid template is needed to pass the product to the angular module.  I used theme.liquid:

{% if template contains "product" %}
<script>
  // <![CDATA[
  ShopifyApp.value("product", {{ product | json }} );
  // ]]>
</script>  
{% endif %}

liquid is not required for Angular App.  I added this as a .js asset.

var ShopifyApp = angular.module('ShopifyApp', [])
.config(function ($interpolateProvider) 
{
  // Change the symbols used to mark Angular code so they do not conflict with Shopify
  $interpolateProvider.startSymbol('{[{').endSymbol('}]}');
})
.controller('VariantSelector', function($scope, product) 
{
  $scope.optionselector = new ShopifyOptionSelector(product);
});

The file with your Angular App needs to be included priory to assigning a value to the module in the liquid template.

I hope this helps others as much as your post helped me.  Thank you.

 

0 Likes
New Member
2 0 0

Love this.  Thank you for the reference!

0 Likes