угловая директива — проблема двусторонней привязки данных

#angularjs #data-binding #angular-directive

#angularjs #привязка данных #angular-директива

Вопрос:

Я изучаю создание пользовательских угловых директив, где я хотел бы использовать некоторую двустороннюю привязку данных; однако безуспешно.

Идея очень проста: у нас есть список людей, где, как только я выбираю любого из них, я хочу отобразить имя выбранного человека (подробно) в моей директиве.

Прежде чем я вставлю много кода, вот мой пример plunker:
https://plnkr.co/edit/xQJAWcYcscOaaNs8VlAI?p=preview

Вот что я сделал:
Создан главный контроллер:

 (function() {
"use strict";
var controllerId = 'personController';
angular.module("app").controller(controllerId, ["$timeout", personController]);

function personController($timeout) {
    var vm = this;
    vm.name = "Janko";
    vm.people = returnPeople();
    vm.selectedPerson = {};
    vm.selectPerson = function (person) {
        //function to add a new Person
        vm.selectedPerson = person;
        console.log(vm.selectedPerson.name);
    };
}

function returnPeople() {
    return [
        {
            name: "Janko",
            surname: "Hrasko",
            age: 24,
            gender: "M"
        },
        {
            name: "Jozef",
            surname: "Mrkvicka",
            age: 26,
            gender: "M"
        },
        {
            name: "Janka",
            surname: "Kratka",
            age: 21,
            gender: "F"
        }
    ];
};
})();
 

Созданная директива:

 (function () {
"use strict";

var app = angular.module("app");

app.directive('personDetail', personDetail);
function personDetail() {
    return {
        scope: {
            person: "=person"
        },
        restrict: 'E',
        templateUrl: '/js/person/templates/personDetail.html'
    }
};
})();
 

** Создан контроллер сведений о персонале: **

 (function() {
"use strict";

var controllerId = 'personDetail';
angular.module("app").controller(controllerId, ["$scope", personController]);

function personController($scope) {
    var vm = this;
    vm.person = $scope.person;
}
})();
 

Наконец — человек Detail.html

 <div ng-controller="personDetail as vm">
  <h3>Selected Name:</h3>
  <h3>{{vm.person.name}}</h3>
</div>
 

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

Редактировать:
Все ваши ответы удалили ng-controller из моего personDetail.html , однако я хотел бы сохранить его (в настоящее время он содержит только одну незначительную привязку, но я хочу добавить туда больше функций, таких как нажатие кнопок и т. Д.).

Возможно ли сохранить контроллер?

Ответ №1:

разметка: <person-detail person="vm.selectedPerson"></person-detail>

 function personDetailsController($scope) {
  var vm = this;
  //vm.person = $scope.person;// This will get executed only first time.
  //Every time you assigning different object to it. Not changing object.property
}
 

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

  function personDetail() {
   return {
      scope: {
         person: "="
      },
      bindToController: true,
      controller:'personDetailsController',
      controllerAs: 'vm',
      restrict: 'E',
      templateUrl: 'personDetail.html'
    }
 };
 

ДЕМОНСТРАЦИЯ

Ответ №2:

Вам необходимо передать выбранного пользователя директиве. Вы предоставили переменную «person» в своей директиве, вам необходимо передать выбранное лицо директиве. А также вам не нужен контроллер для контроллера.

Измените объявление директивы следующим образом:

 <person-detail person="vm.selectedPerson"></person-detail>
 

Отредактировано

Также удалите контроллер в вашей директиве, в этом дополнительном контроллере нет необходимости.

 <div>
  <h3>Selected Name:</h3>
  <h3>{{person.name}}</h3>
</div>
 

Я создал plunkr для демонстрации решения. Вы можете увидеть это здесь.

Комментарии:

1. вы изменили что — нибудь еще , кроме person=vm.selectedPerson ? Я пытался реализовать это в своем локальном решении, но оно по-прежнему не работает… тем не менее, Plunk (который является копией 1-1) работает 🙂

2. Да, я удалил дополнительный контроллер, который вы используете в директиве. Вы можете проверить мой plunkr, которым я поделился.

3. @RobertJ. помогло ли это?

Ответ №3:

вы были почти там. Я обновил ваш plunkr
В index.html вы должны указать объект, к которому вы хотели бы привязаться, следующим образом:

 <person-detail person="vm.selectedPerson"></person-detail>
 

В personDetail.js файл не нужен. И в personDetail.html вы должны заменить vm.person.name на person.name .
Кстати, начиная с angular 1.5, вы можете использовать угловые компоненты, которые несколько проще в использовании.

Ответ №4:

То person , к чему вы привязываетесь, directive должно содержать атрибут в элементе, который вы не указали. Так что передайте это как:

 <person-detail person="vm.selectedPerson"></person-detail>
 

и в шаблоне директивы удалите упоминание об ng-controller="personDetail as vm" использовании его как:

 <div>
  <h3>Selected Name:</h3>
  <h3>{{person.name}}</h3>
</div>