Как установить angular значение свойства объекта контроллера из директивы в области содержимого

У меня есть директива внутри ng-повторителя, которая должна установить свойство scope. Смотрите здесь скрипку: http://jsfiddle.net/paos/CSbRB/

Проблема заключается в том, что свойство scope задано как значение атрибута, подобное этому:

<button ng-update1="inputdata.title">click me</button>

Директива должна установить свойство scope inputdata.title для некоторой строки. Это не работает:

app.directive('ngUpdate1', function() {
    return function(scope, element, attrs) {
        element.bind('click', function() {
            scope.$apply(function() {
                scope[ attrs.ngUpdate1 ] = "Button 1";
            });
        });
    };
});

Однако назначение напрямую работает:

scope["inputdata"]["title"] = "Button 1";

Не могли бы вы рассказать мне, как я могу установить свойство scope. обозначение в его имени из директивы?

PS: Причина, по которой скрипта использует ретранслятор, заключается в том, что он делает директивы в области дочерних объектов. Когда они находятся в дочерней области, вы не можете писать свойства области, которые являются примитивами. Вот почему мне нужно свойство объекта с. во имя. Посмотрите длинное объяснение здесь: Каковы нюансы объема прототипа/прототипного наследования в AngularJS?

Спасибо

Ответ 1

$parse решит вашу проблему.

<button ng-update1="inputdata.title">
app.directive('ngUpdate1', function($parse) {
    return function(scope, element, attrs) {
        var model = $parse(attrs.ngUpdate1);
        console.log(model(scope));  // logs "test"
        element.bind('click', function() {
           model.assign(scope, "Button 1");
           scope.$apply();
        });
    };
});

Fiddle

Всякий раз, когда директива не использует область выделения и вы указываете свойство scope с использованием атрибута, и вы хотите изменить значение, используйте $parse.

Если вам не нужно изменять значение, вы можете вместо этого использовать $eval:

console.log(scope.$eval(attrs.ngUpdate1));

Ответ 2

Не знаю, какова общая цель, но один способ - создать 2 атрибута, один для целевого объекта, а другой для свойства этого объекта:

<button ng-update1  obj="inputdata" prop="title">
app.directive('ngUpdate1', function() {
    return function(scope, element, attrs) {
        element.bind('click', function() {
            scope.$apply(function() {                
                scope[ attrs.obj ][attrs.prop] = "Button 1";               

            });
        });
    };
});

DEMO: http://jsfiddle.net/CSbRB/9/

Альтернативно, используя существующий формат, вы могли бы split() значение вашего текущего атрибута ng-update1 и использовать массив результатов для объекта и свойства в нотации

 element.bind('click', function() {
           var target=attrs.ngUpdate1.split('.');
            scope.$apply(function() {                
                scope[ target[0] ][target[1]] = "Button 1";               

            });
        });

DEMO с обоими подходами: http://jsfiddle.net/CSbRB/10/

Еще один подход, при котором вы создаете изолированную область действия в директиве и можете передать ссылку на объект inputdata и вывести имя свойства из атрибута (такая же разметка как вторая версия):

app.directive('ngUpdate3', function () {
    return {
        scope: {
           targetObject: '=obj'
        },
        link: function (scope, element, attrs) {
            element.bind('click', function () {  
               scope.$apply(function () {
                    scope.targetObject[attrs.prop]='Button 3';

                });
            });
        }
    }
});

http://jsfiddle.net/CSbRB/11/