Search code examples
angularjsdata-bindingangular-directive

angular directive - two way data binding issue


I am learning about creating custom angular directives, where I would like to use some two way data binding; however with no luck.

Idea is super simple: We have a list of people, where once I select any of them, I want to display selected person's name (detail) in my directive.

Before I paste a lot of code, here is my example plunker:
https://plnkr.co/edit/xQJAWcYcscOaaNs8VlAI?p=preview

Here is what I have done:
Created Main Controller:

(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"
        }
    ];
};
})();

Created Directive:

(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'
    }
};
})();

**Created Person Detail Controller: **

(function() {
"use strict";

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

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

Finally - person Detail.html

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

Unfortunately, data binding is not working, even though I can see that the item has been selected. What am I doing wrong here?

Edit:
All of your answers have removed the ng-controller from my personDetail.html, however I would like to keep it (currently it only contains one minor binding, yet I want to add more functionality there such as button clicks etc).

Is it possible to keep the controller?


Solution

  • markup: <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
    }
    

    You can use controller as syntax as follows which also preserve two way binding.

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

    Demo