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

Geppetto and Marionette.AppRouter #5

Closed
zerkalica opened this issue Nov 30, 2012 · 7 comments
Closed

Geppetto and Marionette.AppRouter #5

zerkalica opened this issue Nov 30, 2012 · 7 comments
Labels

Comments

@zerkalica
Copy link

How to use them together ? I can't find it in your example.

@zerkalica
Copy link
Author

  1. I have a layout and some view inside. How to pass view generated event to layout ? Instance view in layout:onRender, pass parentContext to view, and use this.context.dispatchToParent to send message to layout or listen view.context events in layout ? What strategy is better: parent listens child or child sends event to parent (says, render me) ?
  2. In geppetto examples I saw only one context per one view, but not a one context to many views, how to share code and data between widgets?
  3. When to use dispatch, dispatchToParent, dispatchGlobally ?
  4. What is main idea of context ? Without context, widget can listen events, can send them to parent or parent can listen them like context, what difference ?
  5. How to determine what logic should be in the context, and win in the view item ?

@zerkalica
Copy link
Author

I asked this questions on stackoverflow: http://stackoverflow.com/questions/13731124/understanding-backbone-geppetto

@zerkalica
Copy link
Author

What is mediator in your model ?

@geekdave
Copy link
Contributor

geekdave commented Dec 8, 2012

@zerkalica : Thanks for the questions and sorry about the delay in my response. I'll respond to your questions individually as best I can.

Geppetto and Marionette.AppRouter How to use them together

Geppetto doesn't have anything to do with routing, so you should be able to use AppRouter any way you like. Were you having a specific issue?

How to pass view generated event to layout

If the view and sub-view (layout and view) are part of the same logical area, then I prefer them to actually share the same context. Just pass the context object in the options map of your view's constructor function. Then set it from the options to the view instance in the view's initialize() function. This way, the sub-view can communicate with the parent through the shared context. For example:

In your layout:

onRender: function() 
    Backbone.Marionette.Geppetto.bindContext( {
        view: this,
        context: MyContext
    } );

    this.context.listen(this, "someImportantEvent", this.handleSomeImportantEvent);

    var mySubView = new SubView({
        context: this.context
    });
    this.someRegion.show(mySubView);
},
handleSomeImportantEvent: function() {
    // do something
}

In your view:

initialize: function() {
    this.context = this.options.context;
},
handleSomeAction: function() {
    this.context.dispatch("someImportantEvent", {foo: "bar", abc: "123"});
}

Now the sub-view can dispatch events to its own context, and the parent listens for them, without either the layout or the view directly talking to each other.

Now if your sub-view needs to listen to events on the shared context, this was previously problematic. If your view was destroyed, the event binding it created would still live on, and create memory leaks and zombie views. I fixed this in Geppetto v0.3 by requiring calls to listen() to include a first parameter to pass the instance of the component asking for the binding. Geppetto keeps track of which views are bound to which events, and registers a close() handler on the view to clean up those events when the view is closed.

In geppetto examples I saw only one context per one view, but not a one context to many views,
how to share code and data between widgets

The above example kind of covers that, and v0.3 of Geppetto allows you to share one Context to many views, without introducing memory leaks. Generally, if several views are all part of one piece of UI functionality (especially something that would be reused in a few places as one cohesive unit) then it makes sense to have one Context shared between them all.

When to use dispatch, dispatchToParent, dispatchGlobally ?

To tell the truth, I am starting to think dispatchToParent and dispatchGlobally were a bad idea.

I introduced them to support the notion of having one global "shell" view in your app, with its own context. And this shell would handle application-wide events like navigation, alerts, etc. Every child-view would get passed a reference to parentContext to refer to the shell context, and if any sub-section of your app wanted to invoke a navigation event or a notification, they could just dispatch it to the parent context.

I think the above example is better served by using a global namespace for your app (or faking one using RequireJS's "paths" configuration) and storing the reference to the global shell context there.

dispatchGlobally doesn't really serve much of a purpose besides the contrived example in the widget app. So I think I may get rid of these.

What is main idea of context ? Without context, widget can listen events, can send them
to parent or parent can listen them like context, what difference ?

You are absolutely right. You don't need Geppetto or the Context object to have event-driven communication. What Geppetto gives you is the ability to have those events automatically cleaned up when the view that listen()ed for them is closed. But the main power of Geppetto is the Command Map, which allows you to totally isolate your business logic from your views and models. This makes unit testing much easier since you can test your commands in isolation without them being tangled up with your views.

How to determine what logic should be in the context, and win in the view item ?

The context should not contain any logic. It should only contain command mappings. Your backbone view should contain only logic for manipulating that view, and listening for interaction events like clicks from the user. If the view needs to communicate with another part of the app (like requesting some data, or being notified when something happens somewhere else) then the view would listen or dispatch events on its context (or perhaps a context on a global namespace like I described above).

What is mediator in your model ?

The mediator is a part of the "View". I prefer to make the distinction between the "True View" (the HTML and the DOM) and the "View Mediator" which is the Backbone JS code which is sort of "glued" to your View, listening for DOM events, manipulating the DOM, etc. It's a small distinction but I think it's important because it's confusing to have a JS component called the "View" when the DOM is really the true view. It's just semantics. I also describe the mediator in the docs.

I hope this helps! Please let me know what your experience is like using Geppetto and if there's anything else that could be improved.

@zerkalica
Copy link
Author

Thank you for complete answers.

I've been studying the geppetto of 2 weeks and backbone/marionette 3 weeks. Problem, that all examples and documentation describes simple cases. My application is complex and modular, but all this frameworks does not provide complete solution for building modular-architecture:

Backbone does not provide architecture specification itself, only low-level util (model, view, events) for building application. Marionette extends some backbone views and specifies view-layers bricks, but it's controllers and routes not suitable for building gui-like applications with complex multi layered widgets. Geppetto provides better solution for logic-organization, but documentation and example describes simple case.

In your example add-widget-command knows about view: var newWidget = new WidgetView( { ..., so test for this command interacts with view, it's normal behaviour ?

Why in widget-container module, model instanced in widget container view, but in widget-view, model instanced in widget-context. It's normal to use context not only for event commutation and keep some data?

Where can i initialize models and items views: in commands, context or in parent view/layout ?

How to work with marionette layers: layer listen region-specific events and show incoming view in it region?

This diagram shows what i mean a modular architecture. This diagram describes widget for user searching, viewing and editiing in one place: classes_eng.png

@geekdave
Copy link
Contributor

@zerkalica : Sorry for the delay in responding. Yes, the docs and examples need more updates. I'm currently working on a port of TodoMVC to Geppetto which I hope will show some more real-world use cases. Like most open source authors, I'm working on this in my spare time, of which there isn't much. :)

Anyway, I'm not sure if you still need these answers now that it's a month later, but I'll respond just in case.

In your example add-widget-command knows about view: var newWidget = new WidgetView( { ..., so test for this command interacts with view, it's normal behaviour ?

You're right; it's weird that the command knows about the view. Ideally, the parent view would create the child view, not the command. This is a bad example that I wrote early on in the development of Geppetto.

Why in widget-container module, model instanced in widget container view, but in widget-view, model instanced in widget-context. It's normal to use context not only for event commutation and keep some data?

Good catch. See my answer in #7 where I address this very same question. Bottom line is that the Context is a great place to store data that is shared between views.

Where can i initialize models and items views: in commands, context or in parent view/layout ?

Models should be initialized in the Context. Child views should be initialized in their parent views/layouts.

These are great questions, and I thank you for asking. Sorry again for the late response. On my list of things to do is also to add a FAQ to the docs, and your questions will be great for that.

I'm going to close this for now, since it's not really an "issue" per-se. I think it would be good to move this discussion to the mailing list if there's anything else to follow up on.

@zerkalica
Copy link
Author

Ok, models shared in context, child views in parent views, event bus per context, but what about command? Why do you need the command, if domain logic incapsulated in backend and our views only process events from user and other views ?

Most common scenario: user click to UserSearchView (parent widget), each row in search table renders UserSearchItemView, enter search criteria, find user, click them and go to UserView (child widget) and UserEditForm

We have user model and collection, UserSearchView and UserSearchItemView in same context. UserSearchItemView listen click event and redispatch user:selected event to context, sends to parent view.

UserSearchView listens user:selected event and pass selected UserModel to UserView options.

Why we do not need the command in this scenario ?

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

No branches or pull requests

2 participants