knockout / knockout

Knockout makes it easier to create rich, responsive UIs with JavaScript
http://knockoutjs.com/
Other
10.45k stars 1.52k forks source link

Add the concept of observable states #181

Closed rosenfeld closed 12 years ago

rosenfeld commented 12 years ago

While editing data, it is a common request that we should be able to apply the changes or rollback. It is so common that Knockout should help developers here.

An alternative to this problem would be introducing the concept of states. So, an observable could have states. Or we could introduce some ko.statefulObserver()...

When the object changes its state, all current properties could be copied over a new object mapped by the state. For instance, consider that we would have some internal value map:

value['normal'] = {} // all properties would be added to this object

Then, when a user changes a state:

myObservable.changeState('editing')

Then, all values['normal'] would be copied over values['editing'] and all changes would be reflected only on this state.

Templates should be bound to some state. That way, an editing templating would be bound to the 'editing' state and it would respond to changes only on this state while other templates would be affected only by the 'normal' state...

On myObservable.applyState('editing') (equivalent to applyState('editing', 'normal')), those changes would then be copied back to the normal state and reflected on usual templates...

Feel free to ask me any questions if this explanation is not clear enough...

rniemeyer commented 12 years ago

It is not exactly the same as I what you are proposing, but it is pretty easy to build your own objects to do something like this. For example, http://www.knockmeout.net/2011/03/guard-your-model-accept-or-cancel-edits.html

rosenfeld commented 12 years ago

Yes, I've read this article some time ago. It doesn't solve the problem in the right direction IMHO. Take this for instance:

commitAll: function() {
        this.name.commit();
        this.quantity.commit();
},

I shouldn't have to remember each property...

rniemeyer commented 12 years ago

Yes, but that is simple enough to write in a more generic way. Just loop through all properties that are your own, check for a commit function, then call it. It could be done recursively too.

I was trying to stay simple for a blog post.

rosenfeld commented 12 years ago

Yeah, I understand. What I'm saying that this is too much work for a very common requirement for every developer to replicate that I think this should be integrated in Knockout somehow...

rosenfeld commented 12 years ago

But there's another difference between your approach and what I'm suggesting. All templates bound to some specific state should be updated whenever that state is updated...

rniemeyer commented 12 years ago

Yes, I understand that there is a difference. I was not trying to claim that it was the same as your state idea, just that there is room to build these layers on top of Knockout, while keeping the core lean and mean. It would be interesting for you to try to build your idea as a plugin to Knockout and see where the shortcomings might lie that would truly require the core to be enhanced/modified.

As an example, maybe you would be using custom bindings that are aware of an "edit" sub-observable and it would be preferable if the actual bindings handled it natively. Maybe you are passing a "mode" as data into the template binding, when it would be better if the template binding accepted it directly.

rosenfeld commented 12 years ago

I guess we're discussing here if Knockoutjs should be a micro-framework or rather a full-stack framework.

It doesn't matter to me if this could be implemented as a plugin. Personally, when I look for solutions like Knockoutjs, I want it to help solving my problems quickly. That means that common requirements should be pretty easy to implement with this framework. I don't like the idea of getting a separate plugin for getting pretty common requirements...

And plugins have their own problems. They're not maintained alongside with the core source and they will break at some point and if it gets no longer maintained, you'll be stuck to some version for a while until you or someone else takes the maintainance. Also, you always have to check the code to see if it has a good test coverage and if the code is written in a similar way to the core one.

I really prefer using plugins for uncommon requests. I really spend a lot of time before deciding for any Rails plugin when I'm developing the backend. That's because there's a lot to consider and every plugin is a liability. So, it's necessary to take some time to look at the code, to see how big is its community and how often it gets updated as well if they have good test coverage. This really takes lots of time, so it should be delegated for uncommon requests.

RSpec is a good example of a plugin that I wouldn't spend any time choosing it. It has a huge community, is well documented and is evolving super fast and should be kept apart from Rails core since Rails already provides another test framework by default.

But for this particular case, I don't like the idea of solving such a common problem with a plugin. I'm not saying that implementing states is the best way of achieving that goal. I'm really not much concerned on how this goal will be achieved, as long as it is achieved somehow. But I think this should be distributed alongside the core components.

sagacity commented 12 years ago

But what you consider core functionality, implemented in a certain way, may be something someone else considers useless. And by dragging this into the main library, you are increasing the time it will take to do a new release since there's a lot of additional code to be maintained.

rosenfeld commented 12 years ago

This is exactly my point. If this editing feature is considered as a core functionality only by me and a few others, then I agree with you that it shouldn't be introduced in Knockout itself. If most developers find this needed, then I think it should be included.

Anyway, I'm still experimenting with Knockout. I'm just starting to rewrite part of my application using Knockout while I'm evaluating it. So, I'm trying to know it better. If I don't think it suits my application needs, I'll try other approaches... What I'm trying to figure out is what JS framework/library will suit my developer's needs better. I really like the MVVM pattern, but there's still more to take into account before deciding against the final solution...

sagacity commented 12 years ago

It might also be worthwhile to ask for other people's opinion on the Knockout Google Group: https://groups.google.com/forum/?fromgroups#!forum/knockoutjs

SteveSanderson commented 12 years ago

I agree with all of you :)

As it just so happens, the JavaScript client libraries team in Microsoft (which I'm on) is currently working on a rich data access library for JS apps, and one of its features is exactly what you're asking for: change tracking of arbitrary object graphs, with the ability to see what changes have been buffered up, and then sync them back to the server or revert them so the original state reappears (plus various other features like validation and so on). It's going to fit in great alongside Knockout - so KO can do your visible UI, and the new library can do the underlying data access. It will be usable with any server-side technology that exposes a JSON API.

I don't have a schedule for how soon this is going to be available, so I guess it might not solve your immediate requirements, but hopefully I'll be able to do some blog posts soon showing preview builds.

Is it OK if I close this issue for now, since there isn't any immediate action to be taken? If not, please reopen.

rosenfeld commented 12 years ago

Great news! Thanks

Prinzhorn commented 12 years ago

@SteveSanderson Any news on that? Or did it happen and I missed it?