3

My case is that I want to use the createSearchChoice feature of the Select2 widget. So I found out I need to use an html input element instead of a select element and so I cannot use ng-repeat to populate the select2 widget. I find out there is a 'data' option and have been able to populate the select2 widget with static data, but not when I've tried to fill it dynamically.

What works:

html: <input class='select2' ui-select2='sel2props' type='hidden'>

in the controller:

$scope.sel2props = {
    createSearchChoice: ...

  data: [ 
    { id: 0, text: 'yabba' }
    etc
  ]
};

But if I try to set data to a variable which I can then set to whatever the database feeds me the widget isn't populated.

data: $scope.data;

function to retrieve data {
    $scope.data = retrieved data;
}

the retrieved data is exactly in the way specified.

If i set up a button to append the data key it will work:

$scope.appenddata = function () {
  $scope.data.push({id:1, text: 'anot'});
};

So I'm thinking it's a timing issue and I try $digest and $apply but they don't work in controllers. I tried to set up a directive and actually can do simple widgets, but not select2, so I was hoping not to go down that path, well that is to say I went down that path and drowned. If anyone could help out that would be great.

3
  • What do you mean with "I try $digest and $apply but they don't work in controllers"? They work in any place that has access to the scope. Did you run it like this $scope.$apply()? Commented Feb 5, 2013 at 22:30
  • @ bmleite. Incorrect. you'll get an error: $apply already in progress within a controller. Commented Feb 5, 2013 at 23:36
  • That's because you're calling $apply on the wrong place. It has nothing to do with the controller. If you want a simple way to avoid the error, replace all calls to $scope.$apply() inside the controller with $scope.$$phase || $scope.$apply(). Note that this won't fix your problem, it will just avoid the error. Please provide a jsfiddle with your problem. Commented Feb 6, 2013 at 1:26

3 Answers 3

5

The solution is straight forward. Just push the elements onto the select2 data array rather than referencing another array.

Sign up to request clarification or add additional context in comments.

1 Comment

I had gone blind on this as well.. Reading your answer freed my mind; "YES off course!", why am I doing $scope.tags = [], 2 times...?
1
function (result) {
  $scope.lookupOptions.data.length = 0; // remove old items
  angular.extend($scope.lookupOptions.data, result.data); // add new items                  
}

Comments

-2

A trick I've recently made use of is to use Select2's query option to pass in your latest data on demand.

I've put together an example, wrapped in a custom directive. See this Plunk.

3 Comments

Thanks, but i want the user to add data hence the createSearchChoice option and the use of input instead of select. Also, your directive isn't handling the data very well: it includes an html span element for each option.
Do you want the data created by the user to be sent back to the database? Are you interested in a "multiple" select instead of a dropdown? I am using an <input> to create the select2 widget; select2 creates a dropdown like that when in single-select mode but that can easily change. Also, what do you mean I'm not "handling the data very well"? Select2 creates those HTML <span> elements in order to display the dropdown. I'll be happy to update my answer; I was only answering your immediate problem of dynamically adding data to Select2 when you retrieve data from your database.
the spans were showing in the dropdown when i first looked at your plunk, but they aren't now. so i don't know what that was about. The solution to mine was to push on each element to the data array rather than referencing another array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.