nofear87
nofear87

Reputation: 869

Find scope of clicked element in ng-repeat

is it possible to get the clicked row (scope) of a element in ng-repeat without nowing the name?

For example: scope.person works, but when I change persons into another name I can't use my directive global.

I need the data to do a edit like this: http://vitalets.github.io/x-editable/

I will write a directive which changes the text into a input field. To save it I need the name of the field, "lastname" in the example and the ID from the row.

HTML:

<tr ng-repeat="person in persons | orderBy:lastname">
    <td class="editable">{{person.lastname}}</td>
    <td>{{person.surname}}</td>
</tr>

Directive:

app.directive('editable', [function () {
    return {
        restrict: 'C',
        link: function (scope, elem, attrs) {
            elem.bind('click', function(event) {
                console.log(scope.person)
            });
        }
    };
}])

Upvotes: 2

Views: 1072

Answers (4)

robBerto
robBerto

Reputation: 196

Browse how works the custom directives in angular. You can pass like parameter the lastname through 'attrs' in your link. Something like this:

html code:

<my-first-directive lastname="{{person.lastname}}"></my-first-directive>

custom directive code:

link: function (scope, elem, attrs) {
        elem.bind('click', function(event) {
            console.log(attrs['lastname'])
        });
}

This approach not is good in my opinion. But i hope it works you.

If you read about scopes in directives you will can try other approachs. You can pass the same parameter to directive scope so.

In your directive:

return {
    restrict: 'C',
    scope: {
        lastname: '=' // If you want know more about this, read about scopes in directives
    }
    link: function (scope, elem, attrs) {
        elem.bind('click', function(event) {
            console.log(scope.lastname) // now, scope.lastname is in your directive scope
        });
    }
};

Be careful whit names when you work with directives. If your variable is 'myVar', when you write the directive html code you need write:

<my-first-directive my-var="myVar"></my-first-directive>

For the same reason that you need write 'my-first-directive' when you name directive is 'myFirstDirective'.

Good luck!

Upvotes: 1

Skander.B
Skander.B

Reputation: 61

Add a Scope to your directive so you can pass any Model to be edited. And display the ID with the Attrs variable.

app.directive('editable', [function () {
return {
    scope: {
        model : '='
    },
    restrict: 'C',
    link: function (scope, elem, attrs) {
        elem.bind('click', function(event) {
            alert(scope.model +" "+ attrs.id )
        });
    }
};}]);

the html:

<span class="editable" model="person.lastname" id="{{$index}}">{{person.lastname}}</span>

The Fiddle

Upvotes: 1

squiroid
squiroid

Reputation: 14027

You are already catching the current scope and it is working fine you just need to manipulate the data and apply scope.$apply();

app.directive('editable', [function () {
    return {
        restrict: 'C',
        link: function (scope, elem, attrs) {
            elem.bind('click', function(event) {
              console.log(scope.person)
              scope.person.surname="hello"
                 console.log(scope.person)
                 scope.$apply();
            });
        }
    };
}])

In the first console output you can see the original clicked element and in second console you can see the maupilated data.

Now why apply is required:- It is required to run the digest cycle of angular to adapt the change happen outside the scope of angular js (bind is jquery event not angular's).

Plunker

Upvotes: 1

DonJuwe
DonJuwe

Reputation: 4563

You can use Angular's tracking ng-repeats by $index and pass it to your directive:

HTML:

<tr ng-repeat="person in persons | orderBy:lastname">
    <td editable="$index" class="editable">{{person.lastname}}</td>
    <td>{{person.surname}}</td>
</tr>

Directive:

app.directive('editable', [function () {
    return {
       restrict: 'A',
       link: function (scope, elem, attrs) {
           elem.bind('click', function(event) {
               console.log(attrs.Editable);
           });
       }
    };
}])

Upvotes: 2

Related Questions