indrimuska / angular-selector

A native AngularJS directive that transform a simple <select> box into a full html select with typeahead.
http://indrimuska.github.io/angular-selector
MIT License
96 stars 36 forks source link

Cannot clear model/value with remote #34

Closed andreialecu closed 8 years ago

andreialecu commented 8 years ago

Because of https://github.com/indrimuska/angular-selector/blob/master/src/angular-selector.js#L417 any change to the model from code does not properly clear the value from the select box.

I'm not sure what the proper solution here is, but for now removing the || remote check allows me to properly clear the model and get it reflected in the control.

indrimuska commented 8 years ago

Hi @andreialecu, can you provide a valid example showing this issue? I've just tried this plunker, but I am not able to reproduce the problem.

andreialecu commented 8 years ago

Here's an example based on your Plunk:

http://plnkr.co/edit/SWVbujcrHorsBDbn66qC?p=preview

There is a second problem here however.

The underlying problem is hard to fix in this case, because the data from the remote may not be available, so I'm not sure how to fix the root of the problem to allow the dropdown to properly update itself when a remote is used.

Uncomment the line in setBrowsers to see what I mean about the second problem.

andreialecu commented 8 years ago

One possible idea for the second problem is to implement something like:

  <select selector
    model="browser"
    remote="getBrowsers(input)"
    remote-set="getValues(value)"
    value-attr="value"></select>
  $scope.getValues = function (valueBeingSet) {
    // return promise here that is used to populate the dropdown 
    // when the model is updated outside of this directive
    // in this case it can be simply
    return $scope.getBrowsers();
  };
indrimuska commented 8 years ago

Ok, I forgot to add the remote configuration. Now I can see the problem and the solution you have proposed is correct, so let's go for it. About your second problem, it can be fixed by adding some other changes. Let me fix this in a minute.

indrimuska commented 8 years ago

I've just released v1.3.3, let me know if this solves your issues. :)

indrimuska commented 8 years ago

I'm going to close this issue. Feel free to open it again if you still have any problem.

andreialecu commented 8 years ago

This still doesn't work btw, check the plunker.

indrimuska commented 8 years ago

GitHub CDN is not aligned to the last version of Angular Selector, you need to update the urls:

andreialecu commented 8 years ago

They are, I see the same contents here: http://cdn.rawgit.com/indrimuska/angular-selector/master/dist/angular-selector.js as in the other one.

andreialecu commented 8 years ago

Actually, hold on, the plunker works now, but my app doesn't. I'm looking into why now.

andreialecu commented 8 years ago

I'm trying to create a repro, but the problem is here:

https://github.com/indrimuska/angular-selector/blob/master/src/angular-selector.js#L422

scope.options.length is 0 when the newValue comes in with null, so the selectedValues property is never cleared, and when the code runs .updateValue() here:

                // Update value
                scope.updateValue = function (origin) {
                    if (!angular.isDefined(origin)) origin = scope.selectedValues;
                    scope.setValue(!scope.multiple ? origin[0] : origin);
                };

It sets it right back to origin[0] which is the same item I'm trying to clear.

andreialecu commented 8 years ago

@indrimuska Here's the new repro of the bug: http://plnkr.co/edit/Q6iuKmHJNlD2e8oSLHrb?p=preview

There is a line in the js without which everything works, but in real life apps, it will behave more like this repro.

Start typing Safari, select it, then click the button. Won't get cleared.

andreialecu commented 8 years ago

Unless you have a better fix in mind, adding this line seems to fix it:

                scope.$watch('value', function (newValue, oldValue) {
                    if (angular.equals(newValue, oldValue)) return;
                    if (!scope.remote || scope.options.length > 0) scope.updateSelected();
                    if (!newValue && scope.options.length == 0) scope.selectedValues = []; //fix
                    scope.filterOptions();
                    scope.updateValue();
                }, true);
indrimuska commented 8 years ago

Well, what about this plunker? :)

EDIT I think that in a normal scenario, if I don't use any remote configuration and I want to set a certain value (null included) the directive should look for an items in the options array. But what about the behavior when I use remote fetching? Well, in this case I think that the directive should defer the request to the server, which must take care to verify if the option exists or not. To do this, my plan is to pass the value, that you set from your controller, to the remote request. That's the explanation of the plunker.

What are your thoughts?

indrimuska commented 8 years ago

This conversation has been moved to #40.