当加载数据需要一段时间时,Watcher'asleep'

问题描述 投票:0回答:1

我写了一条指令,该指令可以自动扩展返回键上的文本区域。但是,当我预填充textarea时,我希望它增长到内容的大小。

当数据需要一点加载时,我的观察者会入睡。我必须单击文本区域以与其进行交互,以使其最初自动展开。

理想情况下,在初始自动扩展完成后,我想停止监视程序,但不停止输入侦听器。

这是我的代码

angular.module('app',[])

.controller('mainCtrl', function($timeout) {
  var vm = this;
  vm.tab = 1;
  
  //fake async call
  $timeout(function() {
    vm.text = 'fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r ';
  }, 1500);
})

.directive('autoResize', function() {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function autoResizeLink(scope, element, attrs, ngModel) {
      scope.$watch(function() {
          console.log('listen');
          if((ngModel.$viewValue || ngModel.$modelValue) && element[0].scrollHeight > 0) {
              console.log('view value appeared', ngModel.$viewValue);
              console.log('element[0].scrollHeight',element[0].scrollHeight);

              element.css({ 'height': 'auto', 'overflow-y': 'hidden' });
              element.css('height', element[0].scrollHeight + 'px');

              console.log('stop listening here');
          }
      });

      element.on('input', function () {
          element.css({ 'height': 'auto', 'overflow-y': 'hidden' });
          element.css('height', element[0].scrollHeight + 'px');

      });
    }
  }
});
a {
  text-decoration: underline;
  color: blue;
  cursor: pointer;
}
<html ng-app="app">
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
  </head>
  
  <body>
    <div ng-controller="mainCtrl as vm">
 
      <a ng-click="vm.tab = 1">Tab 1</a>
      <a ng-click="vm.tab = 2">Tab 2</a>
      
      <div ng-show="vm.tab === 2">
         <textarea auto-resize ng-model="vm.text"></textarea>
      </div>
    </div>
  </body>
</html>
javascript angularjs angularjs-directive
1个回答
0
投票

代替使用监视程序,而使用$formatters$viewChangeListeners管道:

app.directive('autoResize', function($timeout) {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function autoResizeLink(scope, element, attrs, ngModel) {
      ngModel.$formatters.push(function(data) {
          $timeout(resize);
          return data;
      });

      ngModel.$viewChangeListeners.push(function() {
          $timeout(resize);
      });

      function resize() {
          console.log("resize");
          element.css({ 'height': 'auto', 'overflow-y': 'hidden' });
          element.css('height', element[0].scrollHeight + 'px');
      }
    }
  }
});

ngModelController从框架获取新模型值时会调用$formatters函数。当它从用户那里获取新值时,它将调用$viewChangeListeners

DEMO

angular.module('app',[])

.controller('mainCtrl', function($timeout) {
  var vm = this;
  vm.tab = 1;
  
  //fake async call
  $timeout(function() {
    console.log("data");
    vm.text = 'fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r fsafsafsafasfsa \r ';
  }, 1500);
})

.directive('autoResize', function($timeout) {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function autoResizeLink(scope, element, attrs, ngModel) {
      ngModel.$formatters.push(function(data) {
          $timeout(resize);
          return data;
      });

      ngModel.$viewChangeListeners.push(function() {
          $timeout(resize);
      });

      function resize() {
          console.log("resize");
          element.css({ 'height': 'auto', 'overflow-y': 'hidden' });
          element.css('height', element[0].scrollHeight + 'px');
      }
    }
  }
});
a {
  text-decoration: underline;
  color: blue;
  cursor: pointer;
}
<html ng-app="app">
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
  </head>
  
  <body>
    <div ng-controller="mainCtrl as vm">
 
      <a ng-click="vm.tab = 1">Tab 1</a>
      <a ng-click="vm.tab = 2">Tab 2</a>
      
      <div ng-if="vm.tab === 2">
         <textarea auto-resize ng-model="vm.text"></textarea>
      </div>
    </div>
  </body>
</html>
© www.soinside.com 2019 - 2024. All rights reserved.