1

我有这个指令,它基本上是 bootstrap 中 typeahead 插件的包装器。一切都像魅力一样运作。但现在我必须在 typeahead 的输入字段中设置初始值。该值在 attrs.init 中作为字符串传递。但我不知道如何将其插入文本字段。

angular.module('rcApp')
  .directive('rcAutocomplete', ['$injector', function ($injector) {
    return {
      scope: {
        model: '@',
        search: '@',
        key: '@',
        show: '@',
        init: '@',
        ngModel: '='
      },
      template: '<input type="text">',
      replace: true,
      restrict: 'E',
      require: 'ngModel',
      link: function (scope, element, attrs) {

        // inject model service
        var service = $injector.get(attrs.model);

        // define search function
        var searchFunction = attrs.search;

        // holds picked object id
        scope.id = 0;

        // holds objects that matched query, mapped by "show" value
        scope.map = {};

        element.on('focusout ac.itempicked', function () {
          scope.$apply(function () {
            scope.ngModel = scope.id;
          });
        });

        // launch typehead plugin
        element.typeahead(
          {
            source: function (query, process) {

              // clear cache
              scope.id = 0;
              scope.map = {};

              service[searchFunction](query).then(function (result) {

                var dataValues = [];

                var fieldsToShow = scope.show.split('|');

                $.each(result.data, function (index, dataItem) {

                  // generate key-show string
                  var valueHash = '';

                  for (var i = 0; i < fieldsToShow.length; i++) {
                    valueHash += dataItem[fieldsToShow[i]] + ' ';
                  }

                  valueHash = $.trim(valueHash);

                  // map results
                  scope.map[valueHash] = dataItem;
                  // prepare return strings
                  dataValues.push(valueHash);
                });

                // return content
                process(dataValues);
              });
            },
            updater: function (item) {
              if (typeof scope.key === 'undefined') {
                scope.id = scope.map[item];
              }
              else {
                scope.id = scope.map[item][scope.key];
              }

              element.trigger('ac.itempicked');

              return item;
            }
          }
        );
      }
    };
  }]);

** 更新 **

对我有用的解决方案是将这样的代码添加到链接功能:

// init value
if (typeof attrs.init !== 'undefined') {
   window.setTimeout(function () {
      element.val(attrs.init);
      scope.$apply();
   }, 10);
}

但我仍然不太明白为什么“element.val(attrs.init);” 不要更新视图,调用 scope.$apply() 会,但会抛出“$digest already in progress”错误。将它包装在 window.setTimeout 中会有所帮助,但这对我来说也是一个技巧......

它必须是一种让它更清洁/更简单的方法......

4

0 回答 0