最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Use select2 plugin in AngularJS application - Stack Overflow

programmeradmin1浏览0评论

I use select2 plugin in my AngularJS application for displaying list of some entities (tags). This is my template's part:

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

and this is my scope code's part:

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

I want to provide ability to quickly add a new tag if it isn't exist in the tags list. So I override formatNoMatches select2 option to display 'add new tag' link. How I should properly bind addTag() function from $scope to the click event of the link?

I use select2 plugin in my AngularJS application for displaying list of some entities (tags). This is my template's part:

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

and this is my scope code's part:

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

I want to provide ability to quickly add a new tag if it isn't exist in the tags list. So I override formatNoMatches select2 option to display 'add new tag' link. How I should properly bind addTag() function from $scope to the click event of the link?

Share asked Jul 10, 2013 at 13:41 DmitriyDmitriy 7032 gold badges13 silver badges26 bronze badges 2
  • can you add it in a scope .. ie. $scope.addTag = function() { } – insomiac Commented Aug 25, 2013 at 20:55
  • I have been fighting with the same issues for many days now. I get the feeling that angular needs to be told about the <a> tag that we are making. But I cannot figure out how. – Manu Commented Aug 30, 2013 at 15:44
Add a ment  | 

2 Answers 2

Reset to default 6

The key to the solution of this problem is that you have to use the $pile service on the HTML returned by the formatNoMatches function in the options object. This pilation step will wire up the ng-click directive in the markup to the scope. Unfortunately, that is a bit easier said than done.

You can see the full working example here: http://jsfiddle/jLD42/4/

There is no way that I know of for AngularJS to watch the select2 control to monitor the results of a search, so we must inform the controller when no results are found. This is easy to do through the formatNoMatches function:

$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;
    }
};

The $scope.noResultsTag property keeps track of the last value entered by the user that returned no matches. Wrapping the update to the $scope.noResultsTag with $scope.$apply is necessary because formatNoMatches is called outside the context of the AngularJS digest loop.

We can watch $scope.noResultsTag and pile the formatNoMatches markup when changes occur:

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

You may wonder what the $timeout is doing there. It is used to avoid the race condition between the select2 control updating the DOM with the formatNoMatches markup and the watch function trying to pile that markup. Otherwise, there is a good chance that the $('.select2-no-results') selector will not find what it is looking for and the pilation step won't have anything to pile.

Once the add tag link has been piled, the ng-click directive will be able to call the addTag function on the controller. You can see this in action in the jsFiddle. Clicking the add tag link will update the Tags array with the search term you enter into the select2 control and you will be able to see it in the markup and the options list the next time you enter a new search term into the select2 control.

You can refer this :

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;
        }
    };



};

Working Fiddle : Quickly add a new tag

发布评论

评论列表(0)

  1. 暂无评论