Is this architecture still valid under Angular 1.2 and above Is this architecture still valid under Angular 1.2 and above angularjs angularjs

Is this architecture still valid under Angular 1.2 and above


is this type of code still valid and considered a good practice?

This code is valid, but considered deprecated as of 1.2.0-rc3. It will work in all version of angular 1.2 and 1.3 up to but not including 1.3.0-beta10, where automatic promise unwrapping has been removed.

$scope.stocks.push(Stock.create(result));

In the line above you've created an array of promise objects on $scope. Then in index.html.erb you are referencing the promise directly via the stock iterator:

<li ng-repeat="stock in stocks">      <div id='symbol'>        {{stock.symbol}}      </div>

The non-deprecated way of handling promises does not allow you to bind directly to the promise like this.

How would this code respond to an error state?

The app is handling errors here:

}, function(error) {  $scope.error = true;});

and here:

<div ng-show="error">    There was a problem with the Yahoo Finance API. Please try again later.</div>

For error handling, you're not binding with a promise directly so this works fine in all versions of angular.

A better way?

First, shelf the javascript directory structure in the stockwatch example. Then, follow this directory structure instead. Finally, integrate Restangular into your project. Create a stockModel factory that internally instantiates a Restangular object, but returns the object that will be populated later after the promise resolves (model). Instead of binding a promise in your partial, bind the unpopulated result object.

.factory('stocksModel', function (Restangular) {  var model = {};  var rest_stocks = Restangular.all('stocks');  model.doSomethingRESTful = function (...) {    // return a promise in case the controller needs it    return rest_carts.some_restangular_method(...)      .then(function() {        model.some_data_which_was_acquired_RESTfully = ...;      });  };  return model;});

In your controller:

$scope.stocks = stocksModel;

In your partial:

{{stocks.some_data_which_was_acquired_RESTfully}}


To be blunt

No. If possible, I would improve the code so that is it more maintainable and update to date with Angular. Let me explain why it is a good idea. . .

Why are you making your life so hard?

Angular is a wonderful framework that lets you tackle fairly complex problems with simple solutions. The dark side of Angular is it is easy to over engineer a solution if you go off the beaten path. Angular exposes a lot of the internals so it is tempting (and fun!) to muck around with it instead of going for the simple route.

Growing pains

I believe what you are dealing with is due to the growing pains Angular has had as it matured as project. A lot of side projects sprung up to fix the leaky holes that have since been plugged.

Rails and Angular, fast friends

So I am basing this off of how I have grown to use Rails with Angular. The examples are pulled from a pet project that is not going anywhere. Unfortunately, this is all in coffeescript, so hopefully that wont cause you problems. It is structured how I found works best with Rails, while keeping the spirit and fun of Angular.

* app/assets/javascripts   * app       * project_name_app.js.coffee.erb        * controllers           * controllers.js        * directives            * directives.js       * filters               * filters.js       * resources             * resources.js       * services           * services.js

Rails' asset pipeline wraps everything up using the application.js with the include:

//= require app/project_name_app

In the app/project_name_app.js.coffee.erb, it loads all of the directories with the includes

#= require_self#= require app/controllers/controllers#= require app/directives/directives#= require app/filters/filters#= require app/resources/resources#= require app/services/services

Last, each of the sub directories js (controllers.js, directives.js, filters.js, resources.js, services.js) simply loads everything in that directory:

//= require_tree .

With this setup, the project_name_app.js.coffee.erb is loaded first, setting up Angular, the dependencies, and the app configuration. Then the controller, directives, filters, etc are loaded. One of the perks is new javascript added to a sub directory is automatically included thanks to the require_tree.

Keeping the $resource simple

The best $resources are RESTFUL. Meaning that it is the sample URL and the functionality changes based on the http method of the request. The downside is, if you have different URLs, you will probably need multiple resources. An example from the users_resource.js.coffee:

angular.module("DeployerApp.resources").factory "Users", ($resource) ->  $resource "/users.json", {},    index:      method: "GET"      isArray: true      type: "User"angular.module("DeployerApp.resources").factory "User", ($resource) ->  $resource "/users/:user_id.json", {},    show:      method: "GET"    update:      method: "PUT"angular.module("DeployerApp.resources").factory "CurrentUser", ($resource) ->  $resource "/users/current.json", {},    show:      method: "GET"

To get all users, you call Users.index(). To get a single user, you call User.show( user_id: 1 ). Last, a convenience $resource I that often use, to get the current authenticated user, CurrentUser.show().

Pretty straight forward and easy to read, avoiding have to have thick models. Each of the User $resources can be tested separately.

Angular is ready to do the work

You really only need to start mucking with $promise if you have some complicated juggling act when dealing with multiple responses. I have found it is simpler to just pass in the success and error callbacks to the $resource, for example:

CurrentUser.show success = (user) ->    $scope.currentUser = user, error = (data,status) ->    # redirect to login

The variable names help make the code more readable, without them the coffeescript function definitions kind of blend together.

Simpler is always better

You do not need to worry about the $promise.then of the $resource, allowing you to tidying things up.