Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating select from collection automatically #237

Merged
merged 5 commits into from
Jun 16, 2014

Conversation

yousefcisco
Copy link
Contributor

This is a solution to issue #188 where select options need to be updated after the collection is changed/updated.

@yousefcisco
Copy link
Contributor Author

Yes it does, I'll update it tomorrow

@lukesargeant
Copy link

Awesome.

@@ -556,12 +556,12 @@
// Determine if this option is selected.
var isSelected = function() {
if (!isMultiple && optionVal != null && fieldVal != null && optionVal === fieldVal) {
return true
return true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice. thanks :)

@akre54
Copy link
Contributor

akre54 commented May 17, 2014

Awesome. If you could add some tests for this I'll merge it in the next couple days.

Removed event listeners after unstuck is called. Changed it so that the
options are re-rendered on add, remove, reset and sort. This meant that
I had to add in extra lines to manage the event listeners to ensure that
we don't create a huge number of events.
@yousefcisco
Copy link
Contributor Author

I feel like this simple change has gotten a lot bigger than I initially anticipated. Let me know what you guys think of the code though and if it needs more detailed comments. I'll try and get some tests written for this ASAP.

@akre54
Copy link
Contributor

akre54 commented May 18, 2014

Simple changes rarely are ;)

@yousefcisco
Copy link
Contributor Author

Any update on when this is going to be merged?

@akre54
Copy link
Contributor

akre54 commented Jun 15, 2014

Sorry this slipped through the cracks. Given the size of the change I'm tempted to boot on this to your own CollectionView in your app. I know for my app currently we've got all kinds of special behavior for updating models and filtering (see this gist), and I'm tempted to think that this simple change maybe isn't so simple (what happens if you need to do something more advanced, like filtering?).

That said, if there are no objections from anyone else I'll merge tomorrow (ping me if I forget).

@yousefcisco
Copy link
Contributor Author

Wouldn't more advanced functionality that does filtering be included in a custom handler based on the specific needs of the app? Automatically updating a select based on a changing backbone collection seems to be a fairly common use-case.

Thanks!

@akre54
Copy link
Contributor

akre54 commented Jun 15, 2014

Do you have a jsfiddle example somewhere that I can mess with?

@yousefcisco
Copy link
Contributor Author

Yeah, this is the updated fiddle that started all of this http://jsfiddle.net/v4rNk/2/

I ran into a problem with this when I was building a registration form that updated the State/County select when the country changed so the select had to be re-rendered on change to the state collection which was triggered after the country changed. I ended up having to manage the select rendering outside of stickit bindings.

@akre54
Copy link
Contributor

akre54 commented Jun 15, 2014

Try loading your stickit copy from rawgit.com. Github is blocking
hotlinking to it at the moment.

On Sun, Jun 15, 2014 at 2:28 PM, Yousef Cisco notifications@github.com
wrote:

Yeah, this is the updated fiddle that started all of this
http://jsfiddle.net/v4rNk/1/

I ran into a problem with this when I was building a registration form
that updated the State/County select when the country changed so the select
had to be re-rendered on change to the state collection which was triggered
after the country changed. I ended up having to manage the select rendering
outside of stickit bindings.


Reply to this email directly or view it on GitHub
#237 (comment)
.

@yousefcisco
Copy link
Contributor Author

Yeah I just updated my last comment, this link should be working now http://jsfiddle.net/v4rNk/2/

@akre54
Copy link
Contributor

akre54 commented Jun 16, 2014

I'm going to merge this in, but with a caveat that we should probably rethink this somewhere down the line. This is a fine solution for the general case, but I'm not a big fan of blowing away all the select options each time we add or remove a model. It's fine here, and it helps keep the code smaller, but we'll likely revisit this at some point.

Thanks for all your work on this, I'll try to get the next release out soon.

akre54 added a commit that referenced this pull request Jun 16, 2014
Updating select from collection automatically
@akre54 akre54 merged commit d1147ff into nytimes:master Jun 16, 2014
@patrick-radius
Copy link
Contributor

I'm sorry for responding after the merge, haven't been following the repo lately.
But, #231 was actually made for the same "problem", wouldn't it be just as useable?

@akre54
Copy link
Contributor

akre54 commented Jun 23, 2014

They're not mutually exclusive. This one listens on collection events while
the other one does not.

I'm still tempted to move this to a recipe given the complexity of the use
cases involved. It'd be nice to be able to solidify an api for collections
that is overridable with whatever custom logic you need.

What are the major benefits of 231 over this one in your eyes?
On Jun 23, 2014 7:51 AM, "Patrick Radius" notifications@github.com wrote:

I'm sorry for responding after the merge, haven't been following the repo
lately.
But, #231 #231 was
actually made for the same "problem", wouldn't it be just as useable?


Reply to this email directly or view it on GitHub
#237 (comment)
.

@patrick-radius
Copy link
Contributor

Is it possible to opt-in or opt-out of the added behaviour in this version? or is the refreshing for all collections? this version seems to be doing some magic with events:

 + // Remove previously set event listeners by triggering a custom event
 +        collection.trigger('stickit:selectRefresh');
 +        collection.once('stickit:selectRefresh', removeCollectionListeners, this);

removing a listener by triggering the event, doesn't seem right to me...
#231 probably has the benefit of small code-change (only about 2 ADDED lines), simplicity and opt-in (it only 'changes' behaviour when a thenable is used)

I guess this one has the benefit of also being able to respond to other changes after load... but for me personally i don't see where i'd use that.

@yousefcisco
Copy link
Contributor Author

We could probably add logic for opt-in or opt-out but this select re-render was already happening every time the model value was changed, this change simply made it consistent (ie. on colelction update).

I know what you mean about the magic with listeners, initially I didn't want to do this but I found that it was the only way to remove previously bound events and set new ones to stop the number of bound events from rapidly growing. Before an event is bound we trigger an event to unbind the previous event, set the new event and define a listener to unbind the new event. I couldn't find an alternative method to do without affecting any other events that the user might have bound to the collection.

Could you provide a code example of how this would work with #231 ?

@patrick-radius
Copy link
Contributor

@akre54 is right about the two not being mutually exclusive.
So the only code example i can give you is doing an initial loading of a collection, which in our application goes something like this:

'#category': {
                observe: 'category_id',
                selectOptions: {
                    collection: function(){
                        return this.App.request('promisedcollection', 'fomenumap');
                    },
                    labelPath: 'name',
                    valuePath: 'frontoffice_menu_id'
                }
            },

So the promise makes sure the select is filled with the data whenever it is available.
After that the developer is still on it's own when he/she wants to refresh the select again.
But like i said in my previous comment, i don't see at the moment where that would be useable, maybe you could give an example for that?

@yousefcisco
Copy link
Contributor Author

The issue remains is that there's no non-hacky way for the user to update the select when they want, calling this.stickit() causes issues sometimes and fake updating the model value so it re-renders the select is just dirty.

I ran into problems with this when I was building an address form, the State/County select needed to auto-update whenever the user changed the country so it would show states/counties for that country. Calling this.stickit() on change caused a lot of problems and stopped the user from being able to change the country and fake updating the State/County value was just not an option. Other users have run into similar problems with this where a dynamic collection would need to be bound to a select.

@patrick-radius
Copy link
Contributor

I understand

@akre54
Copy link
Contributor

akre54 commented Jun 23, 2014

I agree that adding and removing models is probably a special case enough for
us to leave it up to the user. The best implementation would be overridable
(and by default not listen on any updates).

In our app our dropdowns are checkable and any selected items are hidden
from the list to be shown as card divs in another. This is way too special
for stickit, so we built it our own. Stickit should handle the generic
cases well, but be flexible enough to enable advanced uses.
On Jun 23, 2014 9:43 AM, "Yousef Cisco" notifications@github.com wrote:

The issue remains is that there's no non-hacky way for the user to update
the select when they want, calling this.stickit() causes issues sometimes
and fake updating the model value so it re-renders the select is just dirty.

I ran into problems with this when I was building an address form, the
State/County select needed to auto-update whenever the user changed the
country so it would show states/counties for that country. Calling
this.stickit() on change caused a lot of problems and stopped the user
from being able to change the country and fake updating the State/County
value was just not an option. Other users have run into similar problems
with this where a dynamic collection would need to be bound to a select.


Reply to this email directly or view it on GitHub
#237 (comment)
.

@patrick-radius
Copy link
Contributor

maybe it's better to have an events array in the selectOptions, just like in the 'main' binding...
Allowing developers to opt-in on specific collection events themselves if they'd like...
Also, i'm doubting if the selectOptions entirely is the way to go...
In the main bindings there's already a nice api (the onGet, onSet, update, etc...) built that could be specialised for when observed is a collection (nested or not)

@akre54
Copy link
Contributor

akre54 commented Jun 23, 2014

@pradius-fut 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants