控制器和绑定异步变量

时间:2019-02-14 16:09:47

标签: javascript angularjs

我想使用控制器中定义的变量来控制元素的显示。
但是,如果变量发生异步更改,我的代码将无法正常工作。 在我的示例中,我在方法vm.fruitsetFruit中输出hasFruit的控制台值。
并且在vm.fruit中为setFruit设置了值之后,在hasFruit vm.fruit中的值为undefined
有解决方法的想法吗?
而且我不希望在指令内部调用控制器方法。

UPD。我从exampleController中删除了asyncChoice的定义,@ LeroyStav是如何建议的。我认为他是对的。但这并不能解决问题。

angular.module('app', [])
  .controller('exampleController', exampleController)
  .directive('wrapper', wrapper)
  .directive('asyncChoice', asyncChoice);

function exampleController() {
  var vm = this;
  vm.selectMode = false;
  vm.fruit = undefined;
  vm.hasFruit = hasFruit;
  vm.selectFruit = selectFruit;
  vm.setFruit = setFruit;

  function hasFruit() {
    console.log('hasFruit: ' + vm.fruit);
    return (typeof vm.fruit !== 'undefined');
  }

  function selectFruit() {
    vm.selectMode = true;
  }

  function setFruit(fruit) {
    setTimeout(
      function() {
        vm.fruit = fruit;
        vm.selectMode = false;
        console.log(vm.fruit);
      },
      1000
    );
  }
}

function wrapper() {
  return {
    restrict: 'E',
    trancslude: true,
    controller: 'exampleController',
    controllerAs: 'vm'
  };
}

function asyncChoice() {
  return {
    template: `
  <button ng-click="selectFruit({fruit: ''})"></button>
    <button ng-click="selectFruit({fruit: ''})"></button>
  `,
    scope: {
      selectFruit: '&'
    },
    controller: 'exampleController',
    controllerAs: 'vm'
  }
}

angular.bootstrap(
  document.getElementById('root'), ['app']
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div id="root">
  <wrapper>
    <button ng-if="!vm.hasFruit()" ng-click="vm.selectFruit()">Choice fruit</button>
    <p ng-if="vm.hasFruit()">You choice <span ng-bind="vm.fruit"></span></p>
    <async-choice ng-if="vm.selectMode" select-fruit="vm.setFruit(fruit)"></async-choice>
  </wrapper>
</div>

1 个答案:

答案 0 :(得分:0)

我向$scope提供exampleController,并在执行异步操作后调用$scope.$digest()

angular.module('app', [])
  .controller('exampleController', exampleController)
  .directive('wrapper', wrapper)
  .directive('asyncChoice', asyncChoice);

exampleController.$inject = ['$scope'];

function exampleController($scope) {
  var vm = this;
  vm.selectMode = false;
  vm.fruit = undefined;
  vm.hasFruit = hasFruit;
  vm.selectFruit = selectFruit;
  vm.setFruit = setFruit;

  function hasFruit() {
    console.log('hasFruit: ' + vm.fruit);
    return (typeof vm.fruit !== 'undefined');
  }

  function selectFruit() {
    vm.selectMode = true;
  }

  function setFruit(fruit) {
    setTimeout(
      function() {
        vm.fruit = fruit;
        vm.selectMode = false;
        console.log(vm.fruit);
        $scope.$digest();
      },
      1000
    );
  }
}

function wrapper() {
  return {
    restrict: 'E',
    trancslude: true,
    controller: 'exampleController',
    controllerAs: 'vm'
  };
}

function asyncChoice() {
  return {
    template: `
  <button ng-click="selectFruit({fruit: ''})"></button>
    <button ng-click="selectFruit({fruit: ''})"></button>
  `,
    scope: {
      selectFruit: '&'
    },
    controller: 'exampleController',
    controllerAs: 'vm'
  }
}

angular.bootstrap(
  document.getElementById('root'), ['app']
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div id="root">
  <wrapper>
    <button ng-if="!vm.hasFruit()" ng-click="vm.selectFruit()">Choice fruit</button>
    <p ng-if="vm.hasFruit()">You choice <span ng-bind="vm.fruit"></span></p>
    <async-choice ng-if="vm.selectMode" select-fruit="vm.setFruit(fruit)"></async-choice>
  </wrapper>
</div>