Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS - One controller on two sibling DOM elements

Tags:

angularjs

I'm trying to do a very simple thing. I'm displaying a list of values with Edit links beside them. Clicking the edit link reveals a form that lets you update the value.

(I've simplified the question so the items just have one field "name". My actual use case has more fields, but is canonically equivalent.)

I've run into something that looks like a bug in Angular, but given my limited experience with it, I'm not so sure. Here's how I'm trying to do it:

<div ng-repeat-start="item in items" ng-controller="ItemCtrl as ctrl" ng-hide="ctrl.isEditing">
    <span>Name: {{item.name}}.</span>
    <a href='#' ng-click='ctrl.startEditing()'>Edit</a>
</div>
<div ng-repeat-end ng-show="ctrl.isEditing">
    <input type='text' ng-model='item.name'/>
    <a href='#' ng-click='ctrl.save()'>Save</a>
</div>

My controller looks like this:

app.controller('ItemController', function() {
    this.isEditing = false;
    this.startEditing = function() { this.isEditing = true; }
    this.save = function() { this.isEditing = false; }
});

Clicking on Edit link calls the right controller function, and the first div hides. But the second div does not hide.

When I rearrange the code to look like this (essentially wrapping the two divs with a wrapper element), all is well.

<div ng-repeat="item in items" ng-controller="ItemCtrl as ctrl">
    <div ng-hide="ctrl.isEditing">
        <span>Name: {{item.name}}.</span>
        <a href='#' ng-click='ctrl.startEditing()'>Edit</a>
    </div>
    <div ng-show="ctrl.isEditing">
        <input type='text' ng-model='item.name'/>
        <a href='#' ng-click='ctrl.save()'>Save</a>
    </div>
</div>

Any idea what is technically wrong with the first version? Note that the <input> boxes do get populated with the right values from item.name.

PS: There's a reason why I'm trying to keep the two divs siblings: in my use case, they are actually implemented as two trs which are supposed to appear right below each other in a table.

like image 242
jrharshath Avatar asked Jul 15 '26 14:07

jrharshath


1 Answers

It's not a bug from angular but it is quite logical.

<div ng-repeat-start="item in items" ng-controller="ItemCtrl as ctrl" ng-hide="ctrl.isEditing">
    <span>Name: {{item.name}}.</span>
    <a href='#' ng-click='ctrl.startEditing()'>Edit</a>
</div>

<div ng-repeat-end ng-show="ctrl.isEditing">
    <input type='text' ng-model='item.name'/>
    <a href='#' ng-click='ctrl.save()'>Save</a>
</div>

If you see the above code you have injected controller only to the first div so obviously sibling div doesn't know what is ctrl or ItemCtrl until and unless you do as in you second way.

So if you want to achieve it as sibling, if you are using routing then add the controller attribute in your route path.

So that the controller will be active for that entire template and you can achieve what you want.

Hope it helps.

like image 59
Achu Avatar answered Jul 19 '26 05:07

Achu