Delay in two-way binding in nested directive with selection area

I have a controller containing an isolated scope directive. Whenever the user changes the value in the directive drop-down list, I need to notify the dispatcher of the change. I do this by providing a directive to the callback function and calling this function in the ng-change event in the directive drop-down list. I cannot (and do not want) to use the clock in the parent controller, since I am only interested in user changes here.

My problem is that the values ​​in the controller area have not yet been updated to those specified in the directive via two-way binding during the callback call (I think this is because the callback is called in the same digest-cycle, where changes to the drop-down model were detected, but models from the parent controller will only be updated in subsequent cycles).

Here's a plunker example illustrating the problem (note the console output):

http://plnkr.co/edit/igW4WiV2niFyrMX2zrjM?p=preview

Extract from the relevant parts from the plunker:

Controller:

  ...
  vm.countryChanged = function() {
    console.log('*** countryChanged callback ***');
    console.log('country:', vm.country); // old value here

    $timeout(function() {
      console.log('country (inside timeout):', vm.country); // new value here
    });
  };
  ...

Directive

    ...
    template: '<select ng-model="vm.country" ng-change="vm.onChange()"  ' +
              '        ng-options="country for country in vm.countries">' +
              '</select>',
    scope: {
      country: '=',
      onChange: '&'
    },
    ...

? , $timeout , , , , .

+4
2

, , , , .

. , , , ng-change Angular.

. , , .

- on-change:

<country-chooser 
    country="vm.country" 
    country-change="vm.countryChange($event)">
</country-chooser>

<country-chooser 
    country="vm.country" 
    country-change="vm.country=$event">
</country-chooser>

:

app.directive('countryChooser', function() {
  return {
    template: `<select ng-model="$ctrl.country"
                       ng-change="$ctrl.countryChange({'$event': vm.country})"
                       ng-options="country for country in $ctrl.countries">
              </select>
              `,
    scope: {
      country: '<',
      countryChange: '&'
    },
    bindToController: true,
    controllerAs: '$ctrl',

:

  vm.countryChange = function(country) {
      console.log('*** countryChange callback ***');
      console.log('country:', country);
  };

, .

DEMO PLNKR.


AngularJS v1.5 Angular2 + Ready

app.component('countryChooser', {
    template: `<select ng-model="$ctrl.country"
                       ng-change="$ctrl.countryChange({'$event': vm.country})"
                       ng-options="country for country in $ctrl.countries">
              </select>
              `,
    bindings: {
      countries: '<'
      country: '<',
      countryChange: '&'
    }
});

AngularJS v1.5 , Angular2 +.

Angular2 +, (=). < &.

Angular2 + - .

<country-chooser [(country)]="vm.country">
</country-chooser>

Angular2 + de-sugars :

<country-chooser [country]="vm.country" (countryChange)="vm.country=$event">
</country-chooser>

. @ Angular - ()

+3

plnkr, http://plnkr.co/edit/8XoNEq12VmXKkyBmn9Gd?p=preview

, , , .

vm.country = 'Belarus';

to

vm.country = {name: 'Belarus'};

template: '<select ng-model="vm.country.name" ng-change="vm.onChange()"  ' +
  ' ng-options="country for country in vm.countries">' +
'</select>'
+3

Source: https://habr.com/ru/post/1674481/


All Articles