6

I want to create a simple list and when the user clicks on a button the value is displayed in a span element.

HTML & Controller

<html xmlns:ng="http://angularjs.org">
<script src="http://code.angularjs.org/angular-0.9.19.js" ng:autobind></script>
<script type="text/javascript">
function MyController(){
    this.list = [{name:"Beatles", songs: ["Yellow Submarine", "Helter Skelter", "Lucy in the Sky with Diamonds"]}, {name:"Rolling Stones", songs:["Ruby Tuesday", "Satisfaction", "Jumpin' Jack Flash"] }]

    this.songs = [];

}
</script>
<body ng:controller="MyController">
<p>selected: <span ng:bind="selected" ng:init="selected='none'" /></p>
    <ul>
        <li ng:repeat="artist in list">
            <button ng:click="selected = artist.name" >{{artist.name}}</button>
        </li>
    </ul>
    <!--ol>
        <li ng:repeat="song in songs">
            {{song}}
        </li>
    </ol-->
</body>

I want to dynamically display the list of songs of the clicked artist. Is this the right approach?

1 Answer 1

16

The problem is, that ng:repeat creates new scope, so you are setting selected in current scope, but the span is bound to a parent scope.

There are multiple solutions, defining a method probably the best:

<div ng:controller="MyController">
<p>selected: {{selected.name}}</p>
  <ul>
    <li ng:repeat="artist in list">
      <button ng:click="select(artist)" >{{artist.name}}</button>
    </li>
  </ul>
</div>​

And the controller:

function MyController() {
  var scope = this;

  scope.select = function(artist) {
    scope.selected = artist;
  };

  scope.list = [{
    name: "Beatles",
    songs: ["Yellow Submarine", "Helter Skelter", "Lucy in the Sky with Diamonds"]
  }, {
    name: "Rolling Stones",
    songs: ["Ruby Tuesday", "Satisfaction", "Jumpin' Jack Flash"]
  }];
}​

Here is your example working on jsfiddle: http://jsfiddle.net/vojtajina/ugnkH/2/

Sign up to request clarification or add additional context in comments.

4 Comments

is there a way to do it without create a method in the controller?
Yes, you can, but this solution with controller method is IMHO the best. Here is fiddle with two other solutions jsfiddle.net/vojtajina/ugnkH/3
ok...as last thing just to see if I get it. In my file it wasn't working because I haven't declared the "selected" property in my model, and it was creating it in the scope of the iteration. While in your third example it works because if it doesn't find the property in the "actual" scope it search over the parent scopes before create it?
Not really, scopes inherit prototypically, that's pure javascript thing. So selected = x in template will always set it to current scope. But selectedObject.property = x will set it to selectedObject if it exists in the proto chain. The method on controller keeps a reference on the scope where the method is defined.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.