petermichaux / maria

The MVC framework for JavaScript applications. The real MVC. The Smalltalk MVC. The Gang of Four MVC.
BSD 2-Clause "Simplified" License
764 stars 51 forks source link

Question about Views Raising Events #66

Closed VincentToups closed 11 years ago

VincentToups commented 11 years ago

I thought I'd tap Peter's greater experience with the following question. I have MVC system which consists of a container of a variety of editable objects. Each subobject is backed by a model, and can switch between an editable and non-editable view. If any of the sub-objects are in edit mode, I'd like the enclosing views "save" button to be disabled until they stop editing. Since the same model backs the editable and non-editable views of the sub-objects, no easy event is fired from the objects which the enclosing view could intercept, perhaps via the sub-models passing the event to the enclosing model.

One solution would be to have the views fire an event when the switch from editable to ineditable mode and the parent view intercepts these events and acts appropriate. The other is to have the views call a method on their objects which dispatches an event and the even percolates up through the model tree to the containing model, which triggers a change in the containing view.

A third possibility is to wire it up manually some how. What is the most idiomatic thing to do in this kind of situation?

petermichaux commented 11 years ago

Is your enclosing model an ss.SetModel instance? If so then all events on the enclosed model objects bubble up to the enclosing model. If you set some state on one of the enclosed models (e.g. m.setEditing(true);) and dispatch a change event on that enclosed model then the enclosing model will receive that event and will notify the enclosing view with the bubbling change event. The enclosing view can then update the state of the button.

The Maria TodoMVC example application does something similar. Enclosed to-do items can change their state between incompleted and completed. When the state of one of these enclosed to-do items changes, the enclosing view updates the state of the "check all" checkbox...

https://github.com/tastejs/todomvc/blob/gh-pages/architecture-examples/maria/js/views/TodosView.js#L20

Does that sufficiently answer your question?

VincentToups commented 11 years ago

It sure does - I ended up doing exactly that. One question, though: if we view model's as purely representing data then it might be argued that whether a model is being edited or not is really a matter exclusively concerned with the views, rather than the models and so it is a bit strange that we notify models that they are being edited and they pass that event up through the setmodel to the containing view.

If we wished the views to communicate directly, would we need to mix in the event target methods into our views?

petermichaux commented 11 years ago

You are definitely dipping into the grey area about deciding what is model state and what is view state. This gets quite philosophical.


I think there is no reason to restrict the JavaScript model-layer data to only the set of data that is saved to the server. That is too strict. The JavaScript model-layer exists for the purpose of making the UI work as desired. If some of the state that needs to be shared by multiple views in the UI then it needs to be in the model layer of some sort.

There is one main question I use in a situation like yours. Suppose you have two views of your application visible in the same browser window. By this I mean two of your enclosing views which are observing the same one enclosing model. When one of the enclosed views is being edited, its enclosing view should have its button disabled. Should the other enclosing view also have its button disabled? If the answer is yes then the data about the enclosed model being edited is data that does belong in the model layer. This way both enclosing views can see it and the two enclosing views do not need to know about each other which is important.

Scroll down to the section called "The Grand Finally" at the very end of http://peter.michaux.ca/maria/quick-start-tutorial-for-the-impatient.html for an example of having two views observing the same model.


If the above is not appealing then there is always the possibility of adding a "view model" like in MVVM architecture. The "view model" layer is just a model layer and can be thought of as part of the model layer of MVC but view model objects are intended to have view state. You can easily add view models to a Maria app using maria.Model.subclass just like you would for any other model. I suppose you could say that you are writing your app in the MVVMC style. I've investigated this for almost exactly what you are describing and decided not to do it partly because the JavaScript language does not make it easy for the view model object to mirror all the methods of its wrapped model object. I can explain more if you are interested.


Another option is to have view objects also be models by mixing in the evento.EventTarget. methods like has been done for maria.Model. In the application I'm working on now I am avoiding this. I've tried it in the past and it gets messy.

Another similar option is to explicitly pass information up the view tree by child views calling methods on parent views. We are trying this instead of making the views into models.


Many options here.

VincentToups commented 11 years ago

Peter - thanks very much for the complete reply. I'm heartened to at least learn that my confusion is in some sense legitimate, in that this is an area of ambiguity in the MVC world at large. I already have situations where there are multiple views of the same model, or where one model is passed between multiple views in turn, so the application has become quite complicated.

I ended up encoding some of the view state in the model for this behavior, as you suggested. We'll see if it becomes the wrong decision as time moves on. We can probably close this issue, however.

Incidentally, do you speak French? I'm trying my best to learn, given that I live and work in France these days. I gather from your name that you are either French, Canadian, or possibly Cajun (like me, kind of), although in Louisiana we tend to spell your name Michot.

petermichaux commented 11 years ago

I'm glad you have a solution that is working for you at least for now. Sometimes these things take time to settle into a comfortable position. MVC is a simple idea but using it well is a skill that apparently takes at long time to develop (at least for me.)

Unfortunately I do not speak French despite 6 years of French classes in west coast Canadian schools. Lucky you living in France. It is a beautiful country and I hope to visit again soon.