Search code examples
javascriptangularjssharedcontrollers

AngularJS update text box across controllers


I have the following html:

<div ng-controller="controller as vm">
  <table class="table table-condensed">
    <tr>
      <th>id</th>
      <th>name</th>
      <th>address</th>
    </tr>
    <tr ng-repeat="item in vm.array" >
      <td>{{item.id}}</td>
      <td>{{item.name}}</td>
      <td>{{item.address}}</td>
      <td><button ng-click="vm.edit(item)">pass the value</button></td>
    </tr>
  </table>

  <form>
    name <input type="text" ng-model="vm.item.name" />
    address <input type="text" ng-model="vm.item.address"/>
  </form>

</div>

<div ng-controller="controller as vm" class="container">
  <form>
    name <input type="text" ng-model="vm.item.name" />
    address <input type="text" ng-model="vm.item.address"/>
  </form>
</div>

And the following JS:

angular.module('app', [])
.controller('controller', function($scope) {
var vm = this;
vm.array = [{
  id:1,
  name: 'name1',
  address: 'address1'

}, {
  id:2,
  name: 'name2',
  address: 'address2'
}, {
  id:3,
  name: 'name3',
  address: 'address3'
}];

vm.edit=function(item){
 vm.item = item;
};
});

See this plunker: http://plnkr.co/edit/haMcXdJTxMwQDmCRFJWX?p=preview I want to be able to update the text in the second form at the bottom at the same time I update the first form.

The application I am working on has two panels. On the left side is the list and on the right the form. When I click a row button I want the form on the right to be populated. The right hand html is in a separate file. Sharing the same controller doesn't do it but I can use different controllers but not sure which approach is best or how to achieve it. Do I need a service?

Can anyone point me in the right direction?

Update: The solution I ended up with in here: http://jsfiddle.net/VxafF/

I tried services but the second view model was not being updated when the service was updated. So I tried broadcast and $emit which worked. I understand that using $rootscope is not a good idea. So I will look for another way when I have more time.


Solution

  • For component communication you should use either services or create an angular(1.5+) component with input and output parameter binding. The component will communicate with a parent controller which will be responsible for maintaining state.

    The html in your app.html would contain something similar to below.

    app.html

    <section>Sidebar
    <p>{{vm.item.name}}</p>
    </section>
    <section>Main   
      <my-form-component item="vm.item" on-update="vm.onUpdate($event)"> </my-form-component>    
    <section>
    

    app.controller.js

    app.controller('controller',function($scope) {
       var vm = this;
       vm.item = {name:''};
       vm.onUpdate = function(item) {
       vm.item = item; 
      }
    });
    

    form.component.js

    app.component('myFormComponent', {
      templateUrl: 'myFormTemplate.html',
      bindings: {
       item: '<', 
       onUpdate:'&'
      },
      controller: function() {
        this.$onChanges = function(changeObj) {
        this.onUpdate(changeObj.item); //output item to parent
        }
      }
    });