8

I'd like to do something like:

<div class='row' ng-repeat='row in _.range(0,12)'>
    <div id='{{row}}'></div>
</div>

but when in the controller I try:

function SetterForCatanCtrl($scope) {
    $scope._ = _;
    try {
        var tile = document.getElementById('5');
        tile.style.backgroundImage = "url('aoeu.png')";
    } catch (e) {
        alert(e)
    }
}

getElementById returns null so how can an element's id be set using AngularJS variables?

Graham
  • 7,431
  • 18
  • 59
  • 84
Noel Yap
  • 18,822
  • 21
  • 92
  • 144
  • You could use a custom filter as it is done in http://stackoverflow.com/questions/11873570/angularjs-for-loop-with-numbers-ranges – Olivier.Roger Dec 05 '12 at 07:32
  • @Olivier.Roger, the range works fine. It came from http://stackoverflow.com/questions/13685138/how-to-repeat-elements-in-angularjs. My question is about setting the element's id. That seems not to work. – Noel Yap Dec 05 '12 at 07:40

1 Answers1

14

The function SetterForCatanCtrl is run only once, when angular encounters a ngController directive while it bootstraps your app. When this happens the element you want to access from the DOM doesn't exist yet.

Doing DOM manipulation from a controller is not a good practice, directives are can solve the kind of problem you are facing. Your use case can be solved with CSS and just switching classes but I guess you want to do more than just setting a background image.

DOM manipulation from a controller

You are not asking for custom directives, so a quick solution could done using the ngClick directive and call a method that can switch images

Example HTML

<div ng-controller='ctrl'>
    <div class='row' ng-repeat='row in _.range(0,12)'>
        <div id='{{row}}' ng-click="click($index)">
            <button>{{row}}</button>
        </div>
    </div>
</div>

And JS

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

App.run(function($rootScope) {
  $rootScope._ = _;
});

App.controller('ctrl', function($scope){
    $scope.click = function(idx){
        var elem = document.getElementById(idx);
        console.log('clicked row', idx, elem);   
    };
​});    ​

So when a button is clicked you will get an id and use it to get an element from the DOM. But let me repeat, a for this use case a directive is a better choice.

JSFiddle: http://jsfiddle.net/jaimem/3Cm2Y/

pd: if you load jQuery you can use angular.element(<selector>) to select elements from the DOM.


edit: adding directive example

DOM manipulation from a directive

Using a directive is simpler, since you can just bind an event to the element the directive is applied to

HTML

<h1>Directive</h1>
<div class='row' ng-repeat='row in _.range(0,12)'>
    <div id='{{row}}' my-directive>
        <button>{{row}}</button>
     </div>
</div>

JS

App.directive('myDirective', function(){
    return function(scope, element, attr){
        element.bind('click', function(){        
            console.log('clicked element: ', element, element.html());
        });
    };
});

http://jsfiddle.net/jaimem/3Cm2Y/1/

jaime
  • 41,961
  • 10
  • 82
  • 52
  • I went with what you have in the jsfiddle. Thanks. – Noel Yap Dec 06 '12 at 23:16
  • @jaime thanks! your answer help me a lot! btw, where could I find the doc of `scope, element, attr` in directive ? And why they are without `$` ? what is the different ? I am a newbie of AngularJS. – zx1986 Oct 01 '13 at 07:39