Use select2 plugin in AngularJS application

I am using the select2 plugin in my AngularJS application to display a list of some objects (tags). This is my part of the template:

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

and this is part of my area code:

 $scope.select2Options = { formatNoMatches: function(term) { var message = '<a ng-click="addTag()">  "' + term + '"</a>' console.log(message); return message; } } 

I want to provide the ability to quickly add a new tag if it does not exist in the tag list. Therefore, I override the formatNoMatches select2 parameter to display the add new tag link. How to properly attach the addTag () function from the $ region to the click event of a link?

+7
javascript angularjs jquery-select2
source share
2 answers

The key to solving this problem is that you must use the $ compilation service in the HTML returned by the formatNoMatches function in the options object. At this stage of compilation, the ng-click directive will be created in the markup for the area. Unfortunately, this is a little easier said than done.

Here you can see the full working example: http://jsfiddle.net/jLD42/4/

I do not know how AngularJS can monitor the select2 control to control the search results, so we must tell the controller when the results are not found. This is easily done using 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 $scope.noResultsTag track of the last value entered by the user that did not return matches. Wrapping upgrades to $scope.noResultsTag using $ scope. $ Apply is necessary because formatNoMatches is called outside the context of the digest AnglerJS loop.

We can observe $scope.noResultsTag and compile 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()); $compile(noResultsLink.contents())($scope); }); } }, true); 

You may wonder what the timeout of $ does there. It is used to avoid race conditions between the select2 control updating the DOM with formatNoMatches markup and the watch function trying to compile this markup. Otherwise, there is a good chance that the $('.select2-no-results') selector will not find what it is looking for and will not compile at compile time.

After the link to the add tag has been compiled, the ng-click directive will be able to call the addTag function on the controller. You can see this in action in jsFiddle. By clicking the "Add tag" link, you will update the tag array with the search term that you enter in the select2 control, and you can see it in the markup and the list of options the next time you enter a new search term in the select2 control.

+6
source share

You can refer to 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 script: Quickly add a new tag

+4
source share

All Articles