【问题标题】:Use select2 plugin in AngularJS application在 AngularJS 应用程序中使用 select2 插件
【发布时间】:2013-07-08 11:23:27
【问题描述】:

我在我的 AngularJS 应用程序中使用 select2 插件来显示一些实体(标签)的列表。这是我的模板部分:

select.ddlTags(ui-select2="select2Options", multiple, ng-model="link.tags")
      option(ng-repeat="tag in tags", value="{{tag.id}}") {{tag.name}}

这是我的作用域代码的一部分:

$scope.select2Options = {
  formatNoMatches: function(term) {
    var message = '<a ng-click="addTag()">Добавить тэг "' + term + '"</a>'
    console.log(message); 
    return message;
  }
}

如果标签列表中不存在新标签,我想提供快速添加新标签的功能。所以我覆盖了 formatNoMatches select2 选项以显示“添加新标签”链接。我应该如何正确地将 $scope 中的 addTag() 函数绑定到链接的点击事件?

【问题讨论】:

  • 你能把它添加到一个范围内吗..即。 $scope.addTag = function() { }
  • 我已经与同样的问题作斗争很多天了。我觉得需要告诉 Angular 我们正在制作的 标签。但我不知道怎么做。

标签: javascript angularjs jquery-select2


【解决方案1】:

解决这个问题的关键是你必须对options对象中formatNoMatches函数返回的HTML使用$compile服务。此编译步骤会将标记中的 ng-click 指令连接到范围。不幸的是,说起来容易做起来难。

您可以在此处查看完整的工作示例http://jsfiddle.net/jLD42/4/

据我所知,AngularJS 无法监视 select2 控件来监视搜索结果,因此我们必须在没有找到结果时通知控制器。这很容易通过formatNoMatches 函数实现:

$scope.select2Options = {
    formatNoMatches: function(term) {
        console.log("Term: " + term);
        var message = '<a ng-click="addTag()">Add tag:"' + term + '"</a>';
        if(!$scope.$$phase) {
            $scope.$apply(function() {
                $scope.noResultsTag = term;
            });
        }
        return message;
    }
};

$scope.noResultsTag 属性跟踪用户输入的最后一个未返回匹配项的值。使用 $scope.$apply 将更新包装到 $scope.noResultsTag 是必要的,因为 formatNoMatches 是在 AngularJS 摘要循环的上下文之外调用的。

我们可以观察$scope.noResultsTag并在发生变化时编译formatNoMatches标记:

$scope.$watch('noResultsTag', function(newVal, oldVal) {
    if(newVal && newVal !== oldVal) {
        $timeout(function() {
            var noResultsLink = $('.select2-no-results');
            console.log(noResultsLink.contents());
            $compile(noResultsLink.contents())($scope);
        });
    }
}, true);

您可能想知道 $timeout 在那里做了什么。它用于避免 select2 控件使用 formatNoMatches 标记更新 DOM 与尝试编译该标记的 watch 函数之间的竞争条件。否则,$('.select2-no-results') 选择器很可能找不到它正在寻找的内容,并且编译步骤将没有任何要编译的内容。

一旦添加标签链接被编译,ng-click 指令将能够调用控制器上的addTag 函数。您可以在 jsFiddle 中看到这一点。单击添加标签链接将使用您在 select2 控件中输入的搜索词更新 Tags 数组,并且下次您在 select2 控件中输入新的搜索词时,您将能够在标记和选项列表中看到它。

【讨论】:

  • 似乎运作良好。我一直在努力解决这个问题。谢谢!
【解决方案2】:

你可以参考这个:

HTML

<div ng-controller="MyCtrl">
       <input ng-change="showDialog(tagsSelections)" type="text" ui-select2="tagAllOptions" ng-model="tagsSelections" style="width:300px;" /> 
       <pre> tagsSelection: {{tagsSelections | json}}</pre>        
</div>

JS

var myApp = angular.module('myApp', ['ui.select2']);

function MyCtrl($scope, $timeout) {

    // Initialize with Objects.
    $scope.tagsSelection = [{
        "id": "01",
            "text": "Perl"
    }, {
        "id": "03",
            "text": "JavaScript"
    }];

    $scope.showDialog = function (item) {
        console.log(item); // if you want you can put your some logic.
    };

    $timeout(function () {
        $scope.tagsSelection.push({
            'id': '02',
                'text': 'Java'
        });
    }, 3000);

    $scope.tagData = [{
        "id": "01",
            "text": "Perl"
    }, {
        "id": "02",
            "text": "Java"
    }, {
        "id": "03",
            "text": "JavaScript"
    }, {
        "id": "04",
            "text": "Scala"
    }];

   // to show some add item in good format
    $scope.formatResult = function (data) {
        var markup;
        if (data.n === "new") markup = "<div> <button class='btn-success btn-margin'><i class='icon-plus icon-white'></i> Create :" + data.text + "</button></div>";
        else markup = "<div>" + data.text + "</div>";
        return markup;

    };

    $scope.formatSelection = function (data) {
        return "<b>" + data.text + "</b></div>";
    };

    $scope.tagAllOptions = {
        multiple: true,
        data: $scope.tagData,
        tokenSeparators: [","],
        createSearchChoice: function (term, data) { // this will create extra tags.
            if ($(data).filter(function () {
                return this.v.localeCompare(term) === 0;
            }).length === 0) {
                return {
                    id: term,
                    text: term,
                    n: "new",
                    s: ""
                };
            }
        },
       // initSelection: function(element, callback) { //if you want to set existing tags into select2
   //   callback($(element).data('$ngModelController').$modelValue);
   //  },
        formatResult: $scope.formatResult,
        formatSelection: $scope.formatSelection,
        dropdownCssClass: "bigdrop",
        escapeMarkup: function (m) {
            return m;
        }
    };



};

工作小提琴: Quickly add a new tag

【讨论】:

  • Working Fiddle 在 Chrome 29 中不起作用。未捕获的错误:没有模块:ui.select2
  • 解决方案的问题(实际上是原始问题)是“创建”按钮仍然在 Angular 的摘要周期之外,并且新添加的项目对于 Angular 仍然是未知的。
  • Fiddle 不起作用,因为对 select2 库的引用已损坏。这是一个原始的 GitHub 引用,带有 jsFiddle 不允许的 MIME 类型的 text/plain。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-14
  • 2016-10-08
  • 2016-03-27
  • 2014-02-15
  • 1970-01-01
相关资源
最近更新 更多