2015-10-23 2 views
0

У меня есть страница с большим количеством текстовых полей в виде Excel. Каждый столбец представляет собой один объект, а ячейки в этом столбце содержат свойства объекта. Когда значение в ячейке изменяется (срабатывает, когда ячейка теряет фокус), мне нужно знать измененный объект и свойство, чтобы я мог скопировать значения в одно и то же свойство в других выбранных объектах.Уведомление об изменении свойства в директиве AngularJS

У меня это работает, но это наивный подход, и я думаю, что было бы лучше инкапсулировать это в директиве. Проблема в том, что директива, которую я смог написать, столь же многословна, как и мое первое решение, и, похоже, не является улучшением.

first version просто передает объект и имя свойства функции обработки изменений.

<td> 
    <input ng-model="person.firstName" 
      ng-change="personChanged(person, 'firstName')" 
      ng-model-options="{updateOn: 'blur'}" /> 
</td> 

$scope.personChanged = function(person, property) { 
    alert(person.personId + ' : ' + property); 
} 

second version использует директиву.

<td> 
    <input ng-model="person.firstName" 
      name-changed person="person" property="'firstName'" /> 
</td> 

myApp.directive('nameChanged', function() { 
    return { 
    restrict: 'A', 
    scope: { 
     person: '=', 
     property: '=' 
    }, 
    link: function(scope, element, attrs){ 
     element.bind('change', function(e){ 
     alert(scope.person.personId + ' : ' + scope.property); 
     }); 
    } 
    }; 
}); 

В обоих решениях, я заявляю, объект и имя свойства в атрибутах, что кажется излишним, потому что я уже обеспечили как через ngModel. Каков правильный способ сделать это?

ответ

1

Когда вы пишете ngModel="person.firstname", угловой будет прослушивать любые изменения атрибута firstname, и он сохранит только значение firstname в вашем ngModel (проверьте документацию по ngModel и ngModelController). Это означает, что вы должны передавать другую информацию в своей области действия (например, person.id, property)

Вы должны избегать двустороннего связывания, где можете. Используйте «&» и «@», когда вы привязываете атрибуты к своей области действия.

Оптимизированная версия вашей директивы:

myApp.directive('nameChanged', function() { 
    return { 
    require: 'ngModel', 
    restrict: 'A', 
    scope: { 
     person: '&', 
     property: '@' 
    }, 
    link: function(scope, element, attrs, ngModel){ 
     element.bind('change', function(e){ 

     alert(scope.person().personId + ' : ' + scope.property + ', value is : ' + ngModel.$modelValue) 

     // dispatch your change to upper scopes 
     scope.$emit('nameChanged', {personId : scope.person().personId, property: scope.property, value : ngModel.$modelValue}); 

     }); 
    } 
    }; 
}); 

затем в контроллере обрабатывать это событие:

myApp.controller('peopleController', function($scope) { 
    $scope.people = [new Person(1, 'Homer', 'Simpson'), new Person(2, 'Ned', 'Flanders'), new Person(3, 'Otto', 'Mann')]; 


    $scope.$on('nameChanged', function(event, change){ 
    // changed detected inside one of ours dirctives 
    console.log('changed detected from controller', change)  
    // do what you want with he new value : 'change.value' 

    }) 

}); 

Обратите внимание, что имена событий должны быть в .constant модуле. Это лучше для ремонтопригодности.

Plunker here

Вы можете добиться того, что вы хотите в обоих направлениях (с нг-изменения и в Fn в Вашей области) или с директивой изолята области видимости. Лично мне нравится делать это в директивах, чтобы изолировать ответственность, но это зависит от вас.

+0

Спасибо за ответ, это улучшение. Мне нравится идея инкапсуляции функциональности в директиве, но у меня есть требование, чтобы измененное свойство должно распространяться на другие выбранные объекты, и директива не будет и не должна знать об этом. Я предполагаю, что там, где я повесил трубку, это то, что Угловой знает, какой объект и собственность изменились, но я должен сказать это, чтобы он мог сказать мне. –

+0

Я не понимаю, когда вы говорите: «измененное свойство должно распространяться на другие выбранные объекты». Можете ли вы объяснить мне или сделать другой плункер? спасибо –

+0

Если пользователь включил эту функцию, изменение «Гомера» на «Мардж» изменило бы имена всех людей на «Мардж». Сценарий реального мира заключается в том, что пользователь вводит прогноз на 20 лет, и сумма за этот период равна уровню, поэтому мне нужно дать им простой способ ввести одно и то же значение за каждый год. –

Смежные вопросы