angular-ui/ui-select

ng-model not working with a simple variable on $scope

tkrotoff opened this issue · 13 comments

Inside demo.html, if you replace ng-model="data.custom":

<ui-select ng-model="data.custom">
  ...
</ui-select>

by ng-model="myItem":

<ui-select ng-model="myItem">
  ...
</ui-select>

$scope.myItem never gets set.
It's like ngModelCtrl.$setViewValue(newVal) cannot bind to a simple variable $scope.myItem.

It will work only if ng-model is an object:

  • demo.js: $scope.myItem = {}
  • demo.html: ng-model="myItem.data"

I could not figure out why, any idea?

Try $parent.myItem. Also, you're using angular incorrectly, there is lots of documentation on your specific issue as it's not specific to this repo. Try the same thing with a vanilla form input (non-select)

You're using angular incorrectly [...] Try the same thing with a vanilla form input (non-select)

Are you sure of that? I've been using AngularJS a lot since the 1.0 days and never heard about that. Could you please point out to some documentation, I'm missing something.

Inside AngularJS documentation they use:

<input type="number" ng-model="size" name="size"
       min="0" max="10" integer />
<input type="text" ng-model="length" name="length" smart-float />

Here aswell:

<input type="text" name="input" ng-model="text"
       ng-pattern="word" required ng-trim="false">

Even todomvc:

<input id="new-todo" placeholder="What needs to be done?" ng-model="newTodo" autofocus>

And the AngularJS documentation for NgModelController/$setViewValue/$viewValue shows:

<textarea ng-model="userContent"></textarea>
element.html(ngModel.$viewValue || '');
...
ngModel.$setViewValue(html);

This isn't exactly a bug with ui-select. This is sort of a 'symptom' of the latest versions of AngularJS. By creating a child scope, the ngModelController is now inside of this child scope. I believe in the past this didn't use to be the case (not sure).

Regardless, after mulling it over, I'm not exactly sure how to go about fixing it without dropping the use of ngModel which doesn't make sense.

A simple way to reproduce this problem:

.directive('test', function(){
    return {
      scope: true,
      require: 'ngModel',
      link: function($scope, $elm, $attrs, ngModel) {
        ngModel.$setViewValue('hi');
      }
    }
  })

I recommend instead opening an issue on AngularJS and asking their advice instead.

Thanks for the explanations and opening an issue on AngularJS.

I'm not an asshole in real life. I just play one on television.

Btw, for the time-being if you MUST use this approach, you can bypass this issue by doing $parent.myVal which is just as liable to break as any other non-object-property solution (and generally why the core team considers it wrong).

@tkrotoff any interest in being added as a collaborator to this project? I'm not sure how active @dimirc is at the moment since he may have completed the features he needed.

Why not but I won't add features since I (my client) don't have currently the need for them.

I can refactor the code a bit, remove some hardcoded stuffs, improve doc and examples and simply make it work: I don't think for instance that the Selectize theme has ever been tested.
Also my knowledge on directives techniques is somehow quite limited (I simply re-use from others), I don't fully understand file select.js.

I'm surprised no one has been complaining about the lack of multiselect yet. That's like the one major feature i care about.

@tkrotoff any interest in being added as a collaborator to this project? I'm not sure how active @dimirc is at the moment since he may have completed the features he needed.

I've being very busy but will catch up this weekend, good to see more people involve. 👍

Sorry for bringing it back to life again, but... $parent arent updating my model also

function controller(){
   $scope.editingGeneralCondition = {};
}
<ui-select name="generalCondition" ng-model="$parent.editingGeneralCondition" ng-required="true" theme="bootstrap">

Most probably, I'm making some foolish mistake here.

@thiagodelgado111 just do obj.property instead of $parent.property