70

I am brand new to AngularJS and like what I've seen so far, especially the model / view binding. I'd like to make use of that to construct a simple "add to basket" piece of functionality.

This is my controller so far:

function BasketController($scope) {
    $scope.products = [];

    $scope.AddToBasket = function (Id, name, price, image) {

        ...

    };
}

And this is my HTML:

<a ng-click="AddToBasket('237', 'Laptop', '499.95', '237.png')">Add to basket</a>

Now this works but I highly doubt this is the right way to create a new product object in my model. However this is where my total lack of AngularJS experience comes into play.

If this is not the way to do it, what is best practice?

0

3 Answers 3

86

You could use ng-init in an outer div:

<div ng-init="param='value';">
    <div ng-controller="BasketController" >
        <label>param: {{value}}</label>
    </div>
</div>  

The parameter will then be available in your controller's scope:

function BasketController($scope) {
        console.log($scope.param);
}
Sign up to request clarification or add additional context in comments.

6 Comments

Can't I do this without parent div?
Yes. You can have the ng-init parameter on the same element as the ng-controller attribute if you prefer.
I have problems with having ng-init on the same element as ng-controller. Have this changed or do I something wrong?
This answer is now deprecated. As stated in the update to this similar answer, the angular documentation for ngInit now explicitly states that the only approved use of ng-init is for "aliasing special properties of ngRepeat" (e.g. fooIndex = $index).
@Daryn "angular way" of doing things is using static templates and REST APIs for dynamic content. To get the data, you make HTTP request and get it (via another request). As this may be best practice, in many cases pages are generated dynamically. Also, SEO might be a problem if you are loading data only with AJAX. So I really don't see the point in deprecating that ng-init directive. And I really don't see alternatives to there 2 methods (except some custom directive, which does almost the same as ng-init).
|
65

You could create a basket service. And generally in JS you use objects instead of lots of parameters.

Here's an example: http://jsfiddle.net/2MbZY/

var app = angular.module('myApp', []);

app.factory('basket', function() {
    var items = [];
    var myBasketService = {};

    myBasketService.addItem = function(item) {
        items.push(item);
    };
    myBasketService.removeItem = function(item) {
        var index = items.indexOf(item);
        items.splice(index, 1);
    };
    myBasketService.items = function() {
        return items;
    };

    return myBasketService;
});

function MyCtrl($scope, basket) {
    $scope.newItem = {};
    $scope.basket = basket;    
}

8 Comments

That makes sense - also just taught me how to do services! Nice. Thank you - However how do I create then pass the object to the controller without a series of HTML inputs??
Depends on your use case.. you could do it just about any way you wanted to.
Whats the scope.basketProperties for?
@AndyJoslin How does Angular know how to pass a basket to MyCtrl?
One problem with that approach is that a singleton instance is created and is the same for the entire application, so for specific page sub controllers you might end up with conflicts or with services already having some data. It feels like having a global for storing stuff.
|
2

I'm not very advanced in AngularJS, but my solution would be to use a simple JS class for you cart (in the sense of coffee script) that extend Array.

The beauty of AngularJS is that you can pass you "model" object with ng-click like shown below.

I don't understand the advantage of using a factory, as I find it less pretty that a CoffeeScript class.

My solution could be transformed in a Service, for reusable purpose. But otherwise I don't see any advantage of using tools like factory or service.

class Basket extends Array
  constructor: ->

  add: (item) ->
    @push(item)

  remove: (item) ->
    index = @indexOf(item)
    @.splice(index, 1)

  contains: (item) ->
    @indexOf(item) isnt -1

  indexOf: (item) ->
    indexOf = -1
    @.forEach (stored_item, index) ->
      if (item.id is stored_item.id)
        indexOf = index
    return indexOf

Then you initialize this in your controller and create a function for that action:

 $scope.basket = new Basket()
 $scope.addItemToBasket = (item) ->
   $scope.basket.add(item)

Finally you set up a ng-click to an anchor, here you pass your object (retreived from the database as JSON object) to the function:

li ng-repeat="item in items"
  a href="#" ng-click="addItemToBasket(item)" 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.