Destroying a Backbone Model in a Collection in one step? - collections

Are these two steps mandatory to delete a Model?
var model = collection.get(id);
model.destroy();
collection.remove(model);
Isn't there a way to destroy a model when it is removed from its collection?

Model.bind("remove", function() {
this.destroy();
});
...
var model = new Model();
...
collection.remove(model);
Removing a model from a collection triggers the "remove" event.
So if you want to, you can get models to bind to them and destroy themselves.

Calling collection.reset() without passing any models as arguments will empty the entire collection.
http://backbonejs.org/#Collection-reset

Related

SAPUI5: Retrieve model object in controller

I have a master-detail application that consumes an OData service (declared in manifest.json).
In the detail controller, I bind the model to the view in the following way (this method is attached to a router object).
_onObjectMatched: function(oEvent) {
this.getView().bindElement({
path: "/ContractCompSet('" + oEvent.getParameter("arguments").id + "')",
model: "contracts"
});
}
How can I access the actual bound model object from within this controller?
Closest I got (but seems too be a little too complicated) is as follows
var path = this.getView().getElementBinding('contracts').sPath.substring(1);
var model = this.getView().getModel('contracts').oData[path];
Well your approach isn't to far off and is indeed pretty much the same as hirses.
The point is the binding does not contain "just" the bound model object. It contains the information about model, path to the "bound object" and context. These can be retrieved from the binding. To access the "bound object" you then have basically two paths available.
Get the model and path from the binding and access the "bound object" via the model: (this is what you and hirse outlined)
var path = this.getView().getElementBinding('contracts').sPath;
var boundObject = this.getView().getModel('contracts').getProperty(path);
Or get the context and path and access the "bound object" that way:
var context = this.getView().getElementBinding('contracts').oContext;
var boundObject = context.getProperty(context.getPath());
Without having done to much research into this I would prefer the second option. It just seems more along the line of how the context binding is intended.
I would have thought,
this.getView().getModel('contracts')
gives you the Model Object (as in an object of type sap.ui.model.Model or subclass).
If you are referring to the data in the Model, you can use the following:
this.getView().getModel('contracts').getProperty("/")

Why is it that when I pass a Model to my .Net MVC 4 Controller Action it insists on using it in the Partial Update?

I am intending to pass a Hotel model to my Controller Action - Do some checks/processing on it, then return a potentially different Hotel model rendered in a Partial View.
The problem I'm getting is that if I pass the oHotelParameter Model to the Action then the PartialView uses the model passed to the Action instead of the one passed to the PartialView method.
If I remove the oHotelParameter Parameter from the Action then the View is Rendered as expected using oHotel.
public ActionResult _SaveMasterDetails(Hotel oHotelParameter)
{
//Do some processing on oHotelParameter
//........
Hotel oHotel = new Hotel();
oHotel.GetHotelInfoById(14); //This gets a different Hotel object just for a test
//For some reason oHotel is ignored and oHotelParameter is used instead unless I remove oHotelParameter
return PartialView("_MasterDetails", oHotel);
}
When I debug the View I see that the Model is set to the value I pass to PartialView (oHotel), yet the result I see coming back from the Action contains data from the oHotelParameter object.
In case it makes a difference, I am calling the Action from jQuery ajax.
Can anyone explain why this should happen?
when mvc handles a form post, it fills the ModelState object with the details of the model.
This is when used when the view is rendered again from the post action, this is incase you have thrown the view back out because it has failed validation.
If you want to pass out a new model and not use the view state, then you can call ModelState.Clear() before returning the view and that should let you rebind the view to the new model.
I think that it would help if you had a better understanding of how model binding works when you post back to an action method. In most cases, it is unecessary and inefficient to pass a view model as a parameter to a POST action method. What you are doing is loading the view model into memory twice when you pass your view model as a parameter (assuming a strongly typed view). When you do a post back the model becomes part of the form collection (through model binding) in the request object in the BaseController class that every controller inherits from. All that you need to do is to extract the model from the Form collection in the Request object in the BaseController. It just so happens that there is a handy method, TryUpdateModel to help you do this. Here is how you do it
[POST]
public ActionResult Save()
{
var saveVm = new SaveViewModel();
// TryUpdateModel automatically populates your ViewModel!
// TryUpdateModel also calls ModelState.IsValid and returns
// true if your model is valid (validation attributes etc.)
if (TryUpdateModel(saveVm)
{
// do some work
int id = 1;
var anotherSaveVm = GetSaveVmBySomeId(id);
// do more work with saveVm and anotherSaveVm
// clear the existing model
ModelState.Clear();
return View(anotherSaveVm);
}
// return origonal view model so that the user can correct their errors
return View(saveVm);
}
I think that the data in the form collection contained in the request object is being returned with the view. When you pass the model back to the post action method as a parameter, I believe it is passed in the query string (see Request.QueryString). Most of the time, it is best to only pass one or two primitive type parameters or primitive reverence types such as int? to an action method. There is no need to pass the entire model as it is already contained in the Form collection of the Request object. If you wish to examine the QueryString, seee Request.QueryString.

Alternative to data binding

As an alternative to binding an array collection to a data grid's data provider, could I assign the array collection as the data provider to the data grid on it's creation and everytime the array collection is updated execute invalidateProperties(); invalidateList(); to re-render the data grid?
Does my described approach make sense?
Does my described approach make sense?
Sort of. If you have an arrayCollection ( ac) defined using a get/set method, there is no reason you can't set the dataPRovider on your DataGrid in the set method, every time the data is changed.
If you do that, then you most likely will not have to update the properties or displayList of the DatGrid, because the mere fact of replacing the dataProvider will do it for you.
Something like this:
private var _ac : ArrayCollection;
public function get ac():ArrayCollection){
return this._ac;
}
public function set ac(value:ArrayCollection){
this._ac = value;
this.dataGrid.dataProvider = this.ac;
}
Bingo, every time that the ac value is updated, so will the dataProvider on the DataGrid.

flex multiple array collections with a single datasource

How can I populate multiple datagrids in flex with a single datasource that is filtered differently for each datagrid. I'm assigning the event.result from my remote object call to three different array collections, each with its own filter function. When I assign and refresh the filter functions, they each affect all array collections. So, the results of the last array collection refresh end up in all three datagrids.
You probably need to use ObjectUtil.copy on your event result to have 3 separate ArrayCollections, one for each DataGrid... otherwise they all point at the same memory location of the single ArrayCollection and any changes made to it will be reflected in all DataGrids.
var AC1:ArrayCollection = event.result as ArrayCollection;
var AC2:ArrayCollection = ObjectUtil.copy(AC1) as ArrayCollection;
var AC3:ArrayCollection = ObjectUtil.copy(AC1) as ArrayCollection;
I would make copies of your data provider, ie:
var myDataArray:Array; // this contains your original data.
dataGrid1.dataProvider = new ArrayCollection(myDataArray.concat());
dataGrid2.dataProvider = new ArrayCollection(myDataArray.concat());
dataGrid3.dataProvider = new ArrayCollection(myDataArray.concat());
The solutions that have been provided may not behave as you might wish they would. An ArrayCollection technically consists of a model and a "view" into the model. In my understanding, both the solutions that have been provided create a copy of the model. This means if you add an item to one ArrayCollection it won't show up in another regardless of whether it would match that ArrayCollection's filter. Usually you want it to be a part of the model of the other ArrayCollections as well but only be visible if the added item passes the respective ArrayCollection's filter. You can share the "model" amongst ArrayCollections while having separate views into the model like so:
var collection1:ArrayCollection = new ArrayCollection();
var collection2:ArrayCollection = new ArrayCollection();
collection2.list = collection1.list;
var collection3:ArrayCollection = new ArrayCollection();
collection3.list = collection1.list;
Now you can add an item to any of the three collections and it will show up in the others. However, you can have separate filters and sorts on each individual ArrayCollection and that won't affect what's viewable in the others. You can read more about this here:
http://aaronhardy.com/flex/collections-and-chaining-for-separate-presentation/

MVC - Insert data into multiple entities from same page

I have a single page which collects related data into a series of input fields.
When the user clicks submit I want to insert the data into two different database tables in one go. ie I want to get the primary key from the first insert, and then use it for the second insert operation.
I am hoping to do this all in one go, but I am not sure of the best way to do this with the Models/Entities in MVC.
Are you using LINQ or some other ORM? Typically these will support the ability to add a related entity and handle the foreign key relationships automatically. Typically, what I would do with LINQtoSQL is something like:
var modelA = new ModelA();
var modelB = new ModelB();
UpdateModel( modelA, new string[] { "aProp1", "aProp2", ... } );
UpdateModel( modelB, new string[] { "bProp1", "bProp2", ... } );
using (var context = new DBContext())
{
modelA.ModelB = modelB;
context.ModelA.InsertOnSubmit( modelA );
context.SubmitChanges();
}
This will automatically handle the insertion of modelA and modelB and make sure that the primary key for modelA is set properly in the foreign key for modelB.
If you are doing it by hand, you may have to do it in three steps inside a transaction, first inserting modelA, getting the key from that insert and updating modelB, then inserting modelB with a's data.
EDIT: I've shown this using UpdateModel but you could also do it with model binding with the parameters to the method. This can be a little tricky with multiple models, requiring you have have separate prefixes and use the bind attribute to specify which form parameters go with which model.

Resources