Partial model editing and validation in Backbone - backbone.js

I'm after some advice on how to handle partial editing and validation of a model in Backbone.
I have a payslip model with 20+ properties. The user can edit part of the payslip (e.g. the overtime properties), the app will display a modal dialog and the user can change the four properties related to overtime.
The modal dialog for editing overtime has a related Backbone view 'OvertimeEditor' which contains the view logic. There are 10 such views / modal dialogs for handling different properties.
The Editor views don't interact directly with the models, there's a mediator for this. The mediator calls a parameterised function on the view which populates and displays the modal dialog. When the user hits save the view then calls a parameterised function on the mediator which updates the model properties.
How should I handle validation within a dialog? i.e. I just want to validate the four properties in question, not the entire model.
The editor views don't currently use a model. Should I create models just for use with the editor views? e.g. a PayslipOvertime model? Or should I manually implement validation in the view (doesn't sound right)?

I would consider continuing to maintain a single set of payslip models, each of which contains a collection of properties that have an 'editable' member. This way you can avoid allocating additional objects.
[
{name: "Overtime", value:10, editable:true, required:true },
{name: "hours", value:40, editable:false, required:false },
...
]
If I am understanding your question correctly, I would rather rely on these editable or required properties for validation rather than create additional models.

Related

How to update the view without re-rendering in marionette.js

How to update the view with the model.fetch(), i.e when i fetch the model, the view shouldn't be destroyed or re-rendered. It should just update the new model into view with reseting the previous model.
this.model.fetch({success: this.render.bind(this)});
This code is re-rendering my view..How can i just update the view with new model
Thanks.
There are multiple ways of updating the view based on your need.
If the view is fairly simple, and all that is needed is to automatically update the view on model's fetch, rendering the view again is the simplest(Backbone's sync event on the model can be used, and model events can be handled declaratively using Marionette View's modelEvents hash -http://marionettejs.com/docs/marionette.view.html#viewmodelevents-and-viewcollectionevents)
modelEvents: {'sync': 'render'}
If you have few model attributes that change in a complex view, you could directly update the dom elements via jquery by listening to change events on the model attributes:
modelEvents: {'change:name':'nameChanged'},
nameChanged: function(model, value){ this.$('#name').val(value);}
If Two way data binding between view and model is needed, frameworks like Backbone.stickit can be used to this purpose - https://github.com/NYTimes/backbone.stickit#usage
Whenever you establish a double binding with your model attributes to the templates, your views need to be rendered again to show the changes. So, you can't avoid rendering to show the updated status of your model.
But what I would suggest you to do is to divide your view into subviews. Since, you are using marionette, you can create a main layout which contains all the regions and for each small region, you can define a view .
For example , suppose I have a basic form with my name, current time and age . All of these variables are stored in a model . So, you have a scenario where your name and age hardly changes but the current time is changing every millisecond causing your whole view to re-render which is bad in terms of performance as well as to the eyes.
So, in order to solve the above scenario, if you could create a separate view for the current-time element, you can render is separately and other elements don't need to be rendered again and again. You can always define a separate view for a single button element if you think that its functionality can be abstracted.

Disabling user input within a Marionette collection view - that is being updated by other parts of the application

Need to disable input buttons for items within a Marionette collection view.
Normally I'd just do:
TheView.$el.find('input').prop('disabled', true);
That should disabled all input elements within the view.
The problem I am having is that other parts of the application are updating that view, as a result anything new that comes into the view is not disabled.
What is a good pattern for dealing with this situation?
INHO its not very good to work with ItemView elements from collection view - its better to use custom event or move disable logick to item view.
In case you have other modules updating the view - if i were you i would move disable term in ItemView template - in this case any update will check this term and render input correctlly.

How to make an extjs grid a form field?

I have a requirement to create a custom form field that is basically an extjs grid. The user should be able to click a result in the grid. This clicked result should then become the fields value. Also, this field needs to extend Ext.form.field. Here's what I got:
Ext.define('MyApp.field.Grid', {
alias: 'widget.GriedField',
extend: 'Ext.form.field.Base',
I'm a lot of confused on how to add a grid to form field base. Looks like form field base's template expects HTML. How do I get it accept a component?
If you just need to select a value from a list of items. Why not use a combobox?
If you need to select multiple items. There is an example of how to use the MultiSelect ux component in the documentation examples.
http://docs.sencha.com/ext-js/4-1/#!/example/multiselect/multiselect-demo.html
If you really must use a grid. Then I wouldn't bother with trying to create a field type and cause yourself grief.
Add a listener to your grids selectionchange event and update a hidden field in your form with the value you want from the grid. Job done.
I ended up putting the grid on a form indirectly through creation of dependencies on my model.
My model has master-detail, which the detail is just a store reference. I found that using associations did not work for me.
So, in adding a field to a form, I have something that manages changed events for the model (master record) and the detail stores.

Adding to a collection from a popup modal with Backbone Marionette

I'm pretty new to Backbone and Marionette and am having a tough time getting my views to communicate.
I've got a composite view that displays a list of items. To add a new item to the list, I have a popup modal that opens in a new item view that is separate from the composite view.
I'm not sure that this is the best way to do this, but in the modal, I created a new instance of the collection with all of the items and added the new item to that collection. This new item shows up in the original composite view, but only after I refresh the page.
I can't seem to figure out how to get the composite view to listen for the add event and render the new model after it is added.
Am I on the right track here? If not, what should I be doing to add to a collection from a modal?
I think I got this figured out. Instead of creating a new collection in the modal view, I passed in the collection from the composite view as a parameter when I created the modal view. Now, when I add a new model in the modal, the 'add' event is automatically triggered on both versions of the collection and the view automatically renders the new model. No need to bind any extra events like I was thinking.
Your solution will work, but means your views are pretty tightly coupled. You might want to look into using events instead (see How do I send a model that was clicked on within a ItemView to another ItemView that is on the same page?)
How your functionality would work with events:
Within the modal, you enter the data for the model to create
When you press the "save" button,
you validate and save the model var myNewModel = ...
you trigger an event: MyApp.MySubApp.trigger("item:add", myNewModel)
In the controllerfor the list view, you listen to that event, and add the new model to the collection.
The handler code in your controller would look something like:
MyApp.MySubApp.on("item:add", function(model){
this.myCollection.add(model);
});
If you'd like to learn more about using events, check out 2 Marionette tutorials I wrote:
http://davidsulc.com/blog/2012/04/15/a-simple-backbone-marionette-tutorial/
http://davidsulc.com/blog/2012/05/06/tutorial-a-full-backbone-marionette-application-part-1/
Both use events to communicate information within the apps.
In addition, basic events are also explained here: http://samples.leanpub.com/marionette-gentle-introduction-sample.pdf

views not displayed using viewsphp module

hai
i created a view using custom fields only (using views php module). the problem is that the view is not displayed. but if i add node id as an extra field the view is displayed.
It sounds like the view still needs to know what data to show, and depending on how you set up your view, you may have set it to use exposed filters. Turn off exposed filters. This should disable the required input field.

Resources