Long story short, let's say one app has multiple pages with:
a form
a list
pagination
each page may require (now or in the future) custom actions to be implemented
My question is, witch is the preferred Backbone way of handling this and why (please argument) ?
Define, a pagination view, a pagination collection, a search model, search view, etc, and initialize each one as a child view in all the necessary pages. This means we will have to append child view elements into the 'master' element, and handle all the communication between these in all necessary pages.
Define a pagination view (with it's own pagination collection and search model) and extending it across all the necessary pages. This does mean that we will have to make use of template partials (for forms, pagination, etc) and bypasses the need of handling communication between child views while also removes the need of appending/removing child view elements.
Please add your way of handling these cases if not found above, remember to argument.
My personal opinion would be 2. And that is because it removes a lot of hustle with communication between child views and it makes everything much more easier to read just by extending classes, instead of having to 'manually' init child views. It also gives one the option to rewrite behavior per page when needed.
I think #2 is a poor choice.
It's a very good idea to keep templates as simple as possible. They are basically just the markup that's generated for some input object. In order to get that object to the template, in MV* frameworks you have Views, that can either pass a model to the template or send some formatted data to the template (I prefer this where possible).
Partials just create markup. You'll still have to handle events, updates to the DOM and rendering inside the view. If you only use one view it will have to handle a lot of things, something associated with poor maintainability and a more bug prone codebase.
You'll either have a lot of code in the views, or you'll end up with a lot of mixins or doing a lot of inheritance - and I have no idea which is worse.
Big things are a lot harder to test and to reason about. Avoid doing big things.
I think that another big problem with the template partials approach is the fact that you cannot rely on type information (something like interfaces), on the object that ends up in the template. It's probably easy to make it work when you have a partial or two that you just created, but, in time this information will get lost, leading to a bad development experience.
You'll need to make sure views unrelated to your changes are kept updated with the partial changes you just made for a feature.
Keep in mind that software is never done. Things always change.
Instead of thinking about relationships between models you'll have another complex challenge that you need to handle: the coupling of views through partials.
The alternative is a lot better. Composing specialized views is a good approach because each has it's own internal, smaller state and just it notifies listeners when some action takes place. Nobody cares about what's going on there until something happens and then you just get concrete data.
Going with #1 helps you deal with complexity in your application while allowing you to reuse them in other contexts.
Related
I have a large app with a structure and UI that has been designed to meet the original requirements.
I am now faced with a situation where I have to make an alternative read-only "view" of certain parts of the app for embedding in an iframe (I have no say in this, this is how it has to be).
I'll be referring to these two ways of viewing the app at the "display context".
I am struggling with visualising how to achive this, I can see two solutions both of which have distinct disadvantages:
Have lots of ng-if directives attached to template elements, the ng-if would be bound to the current display context of the app and show/hide elements depending on how it was being used. Even if these were one-time bindings, it would potentially turn the templates into an unreadable mess of nested ng-ifs everywhere
Create entirely separate templates for the two different display contexts. While much cleaner than the first option, it would mean a lot of duplication and maintaining two templates per view whereas previously it would be one.
I should add that the nature of the views is very ng-repeat heavy, a list of data containing categories, each category contains items, each item contains a multitude of data, at each level data may need to be hidden/displayed/manipulated for display depending on the display context. I have made heavy use of directives and components to break things up into logical chunks, however these directives and components are still very much geared towards the original use, rather than the newly required one.
I have also considered creating an entirely new app for this, however I'm not sure this would bring any benefits as I'd be using controllers and injecting services containing tons of stuff that would be never used, I'd also be increasing my duplication problem.
Does anyone have any feeling, suggestions on a good way forward for this as at the moment I'm feeling anything is going to be horrible.
Many thanks
Pretty cryptic question I admit.
I'm looking for references / best practice in updating views based on a GUI event.
Basically I'm seeing 2 different ways to do this:
every view-change is a reaction to a model-change
Gui event
viewhandler (custom or 2-way binding lib) that
updates Model based on view
the View has a listenTo defined on the MOdel that was updated, which gets invoked
do whatever DOM-changes we want
Do DOM-changes directly in the viewhandler
Gui event
viewhandler (custom or 2-way binding lib) that
updates Model based on view
do whatever DOM-changes we want
the View has a listenTo defined on the MOdel that was updated, which gets invoked
The fist approach seems the most clean to me: it can use validation rules on the model, before changing the DOM and the flow just feels better. However, I can't find any good references to back this up. What is generally considered best practice here?
I wouldn't know what is Overall Internet Agreement on that topic, but working on a fairly large Backbone application with complex views, the first approach is what has proven the most maintainable.
One way to see it is that as you know, Backbone's Views and Backbone's Routers are kinda sharing the workload of what would be an actual Controller in a standard MVC (say, Rails). What that means is that in a view, you'll typically have the logic to translate GUI events (click on X) to Model Change (do Y) and the logic to translate Model Changes (new state after Y) into DOM changes. That doesn't mean the logic needs to be in the same place, those are two separate things. Your model may be shared among multiple views and you need your View to react regardless of where the change is originating. You could also be waiting for the server to answer whatever, and so, the DOM update would be in a callback anyway.
A pattern I have been using a lot lately is to have a _renderUpdating() to update the DOM to let the user know that his action has been taking into account (add a spinner near to whatever triggered the change), but I let events do the actual re-rendering once the server has returned the new model.
There is nothing that prevents you from going with the 2nd approach in simple cases, but as your application grow, you'll be very happy to have more than just a single render() that erases everything (including subviews) and you'll be looking at having a clean break between view -> model (which is the role of a controller) and model -> view to allow for more flexibility.
I'm writing a javascript web app using Backbone and Marionette, and my templates are created using Handlebars.
I have a view with three sections: a progress indicator, results list, and footer. Each of these may be shown or hidden based on if an operation is in progress or if there was an error.
Should I include conditional code in the Handlebars template, along the lines of {{unless resultsFetched}} and do this.render() often, or use javascript in the view like this.ui.resultsList.show() and this.ui.resultsList.hide()?
Thanks.
Update
Here are what I think are some pros and cons to having logic in the view templates:
Pros:
I think this looks like a declarative (instead of imperative) style, where the view says that it'll act a certain way based on model state.
As things get more complex, it'd probably be easier to read a template that has conditional logic than javascript code where show() and hide() is used extensively.
Cons:
Is the MVC architecture still being obeyed?
This goes against Mustache's philosophy of logic-less views
As a general rule, you'll want to keep as much logic in the Views as possible and only have presentation in your templates. That isn't always practical to be sure, but the larger your app gets, the cleaner you're going to want your templates to be.
That being said, today I used a for loop in an Underscore template because I had no need for a CollectionView-ItemView combo for the little things in the list that I was adding to the DOM.
TL:DR; Try to stick to my first paragraph, but use your instincts :)
Well , In MVVM pattern it is good practice that two models should not know or talk with each other. That means you should not create a object of one model in other and then register for event or performing similar things.
But why, what is wrong if two models know each other. I am writing the code and what will happen if both my models know each other.
If you are going to circumvent MVVM in any way you want to have a good reason (otherwise you might as well just write it as traditional code-behind and save some typing) :)
There are several benefits of using MVVM, which are mainly to do with very loose coupling, unit testing and reuse.
The basic principal of loose coupling goes something like this:
A View knows how to display data of a certain shape, but has no idea where the data comes from.
A ViewModel provides a certain shape of data and settings, that views can use, but has no idea who is displaying it.
A Model knows how to hold generic data, but no idea who is consuming it
A Controller (missing from most MVVM explanations) decides what data to fetch, what data to display and where to display it. This is where the decision making belongs.
If you require your ViewModels to know about each other, then you are most likely missing a Controller object that manages your 2 ViewModels and associated Models/Views.
If you can provide more information about why your models are currently linked, I may be able to suggest an alternative.
It's often perfectly appropriate for view models to interoperate with each other. Parent/child relationships in the view involve the parent view model holding a collection of child view models, after all. There are any number of circumstances in which, for instance, the availability of commands in the parent view depend on the state of its children. It's sometimes appropriate to delegate this to a separate controller class, but it's also often not worth the effort to do this.
It really depends on the overall complexity of your application. Sometimes that kind of effort is essential; sometimes it's just gold-plating.
In CakePHP I have a layout created and named default.ctp. In that layout I have a sidebar with some blocks and there're some statistics taken from the database.
My solution: I just created model called Sidebar.php and there're some functions, then I set up data in controller to display it in layout. Is this the best solution? As far I know, I will have to re-set every data in every controller, so need suggestions how to solve that.
Bear in mind that this is coming from a 10,000' level - I know nothing of your particular circumstances, but IMO it's not the best solution. I say that because you've created a model that represents a presentation component. If it were me, I'd probably look at using an element for display. Displaying dynamic components gets a little dodgy, but can be done without violating the MVC "covenant".
Your models should represent your domain entities (you've mentioned nothing about what your stats represent, so I won't offer any specific examples), not how they're presented.