How to know when model has changed on front side with Backbone? - javascript

I probably don't understand some of the Backbone logic and so hope you can explain it to me.
When I create a model, pass it an ID and then fetch it, Backbone marks the model as changed (a call to changedAttributes() returns all the object attributes).
When you modify an object attribute on front side, it also marks the model as changed with only this attribute being returned by changedAttributes().
So how do you make a difference between changes made on front-side (and so, not persisted) and changes which comes from the server ? (Is there any specific events ?)
The reason for why I'm asking this is that I'd like to save my model, times to times, if there are some front side changes or if the user quits.
[edit]
My scenario is (I work with Angular):
The URL of my page is of the form: object/#/:id
My page is an editor for the object (some inputs).
When the ID in the URL changes, I fetch the corresponding object from the server. But if there were already something (like if the user manually changes the ID), I need to save whatever has been done on the object first.

There is no real tracking of model/collection changes in Backbone, that tells you what or if something changed. You have to do this by yourself.
You can of course check the changes of the current change loop. So in an event handler you use like model.on("change", () => ...). You might want to implement a handler function, that tracks the change, and maybe reset it, after you saved it on the server

Related

Check for changes in the data of a form without using javascript

I currently have the below javascript to detect changes in my form.
form.addEventListener("input", function () {
ChangesMade = true;
console.log("Change");
});
I now need to include whether or not a change has been made in a call to the controller which means that the value can no long be stored in javascript as this is client side.
You have a couple options...
1. Construct a view model with two instances of your model. One the "original" instance, one the "changed" instance. Bind the "original" fields to hidden inputs in your form, and bind the "changed" fields to your normal form elements.
Then, when the form is posted to the server, your controller action's input would have two instances to compare. If the "changed" values are different from the "original" values, then the user changed something.
Note however that users can still change hidden inputs if they want to. This is not a secure measure, but can be an effective one if "security" isn't a concern here.
2. Keep your view and controller interaction the same as it is, but when the data is posted to the controller you would use the identifier from that record to fetch the original from the database.
Using the posted model and the database-fetched model, compare the two. If values are different then the user changed something.
Note however that this doesn't cover race conditions. It's possible that another user changed the database values since this model was originally shown to this user. You can get around this by adding timestamps of when data was changed, but it might not be enough to tell you what data was changed unless you keep audit copies of old records. The complexity of that escalates quickly.
It's a trade-off between the two options of which one meets the actual needs of the system with acceptable drawbacks.
Send the form data to the server
On the server side load current data from the DB
Compare and test for changes

Loopback - see data before overwriting in "after save" hook

I've seen this question: Strongloop : Compare old model with the new instance in operation hook 'before save'
Is there any way to get the data in the DB before the overwriting is done in the before save hook? Basically, I want to be able to pass one element to update in a put request rather than pass all required fields during the request.
It seems like you are looking for upsertWithWhere or upsert which does a PATCH rather then a PUT. If you do that and the right row can be identified (you send along the primary ID or identify the row) only the passed along data will be updated/overwritten and the rest will be kept.
That's the easy way, if you want to do something more advanced (like doing modifies on DB before a save) then you just have to access the Model in the before save hook and modify. Remember you can do anything before a save as long as you postpone the "next()" call.

How to add a read/write customRestService to support editing in Dojo DataGrid?

I am trying to develop a Dojo DataGrid that returns a user's documents from the categorized BidsByDriver view and allows them to edit the Priority field in the grid. After getting past the hurdle of using the keys property to filter over the categoryFilter, this was easy to set up using an xe:viewFileItemService read/write service. However the problem with xe:viewFileItemService as a data source is it will display empty lines for each entry in the view after showing the user's documents in the grid.
To get around the blank lines I went down the path of creating an xe:customRestService that returned the jasonData for just the current user's documents. This fixes my blank lines problem but my data source is not in the correct read/write format to support the in-grid editing.
Here is the resulting Json data returned form the xe:customRestService ...
[{"Driver":"ddd","BidID":"123","Priority":"1","Trip":"644"},
{"Driver":"ddd","BidID":"123","Priority":"2","Trip":"444"},
{"Driver":"ddd","BidID":"123","Priority":"4","Trip":"344"},
{"Driver":"ddd","BidID":"123","Priority":"4","Trip":"643"}
]
Here are the Dojo modules I am loading:
<xp:this.resources>
<xp:dojoModule name="dojo.store.JsonRest"></xp:dojoModule>
<xp:dojoModule name="dojo.data.ObjectStore"></xp:dojoModule>
</xp:this.resources>
And here is the script to develop the data store for the grid:
<xp:scriptBlock id="scriptBlock2">
<xp:this.value><![CDATA[
var jsonStore = new dojo.store.JsonRest({target: "InGridCustom.xsp/pathinfo"});
var dataStore = dojo.data.ObjectStore({objectStore: jsonStore});
]]></xp:this.value>
</xp:scriptBlock>
All of this works very nicely except for the bit on providing the in-grid editing support. Any ideas appreciated.
How are you trying to save the changes? With a custom REST service, I would not expect that saving the data store would make any changes to the back-end data, which is why a refresh would revert it to the original value.
I would expect that you'd need to write a doPost method in your custom REST service to process the change on the server side, along with client-side code to call the post method and pass in the updates to process (along with the document ID).
UPDATED ANSWER:
I would try one or both of these approaches to fix your issue.
1) Have a category in your view, and use a categoryFilter and use the hack to make the service only return the correct values. Outlines in this question: XPages Dojo Grid editable cell does not save value when REST Service save() method is called
2) Change the rest service type to viewJsonService in combination with #1. If you get an error, double check the configuration document that Per mentioned. Also heed Per's comments in the linked question relating to configuration and using Firebug to make sure the correct method is used. The update must be a PUT, a POST will not work with the viewJsonService.
Original Answer (for context of comments)
Paul,
I believe that you need to have a button with code to save the changes back. Maybe you do, but you don't mention it and it isn't in your screen shots. The step that Per mentioned is very necessary so it is good that you have it taken care of. The button is necessary, to 'commit' the changes back. The act of inline editing doesn't trigger the PUT call. If you think about it, you wouldn't want an update after each change but one update when the user is finished editing.
If you don't figure out by this evening, I have working code that I can send you, but don't have access to at work.

Django modify model instance from HTML

I want to know if it is possible to directly modify and save a model instance in the HTML Template and not via a view and extra URL.
My user has a Boolean Property, I want to display it as a toggle button on the website and the user should be able to toggle it on or off without leaving the website or reloading it.
class User(AbstractBaseUser, PermissionsMixin):
...
autoplay_enabled = models.BooleanField(default=True)
...
Is this possible without an extra view or form?
Basically I just need to set
request.user.autoplay_enabled = False (or True)
and then save() it
If I can't modify the object directly in the HTML template is it at least possible to just execute a function I have defined somewhere in my Python code, without having the need to create a new view?
What you're asking doesn't make any sense at all. HTML is just sent to the browser for display. You can't do anything "from HTML" without making some kind of request to the server, and the server won't do anything unless that request is received by some code - eg a view connected to a URL.
If you want something to happen without refreshing the page, you need to use Ajax. You can use a simple Ajax POST to a view that toggles the value and saves it - it only needs a dozen lines of code between front and back end.

How to bind server side events on client objects and vice versa with meteor

Is it possible to directly bind server side events to client side objects in meteor?
I would like to update a view for example when a server side event triggers. On the other hand I'd like to fire a server side method when a user clicks a view item.
I could use Meteor#methods for all the events but that seems odd.
Or can I specify an eventhandler for example using EventEmitter outside the client- and server-scope so that it is available on both sides and trigger/bind events ob that very object?
Some confused about that I am thankful for hints into the right direction.
Regards
Felix
Update:
Using Meteor#methods works great in case user events should be mapped to server side actions. The other way around is still unclear. Asynchronous actions on serverside could persist their results in a collection which is pub/sub'ed to the client, which in turn could update some view due to the reactive context. But thats odd, cause persisting that kind of info is slow, wasted space and time. Any suggestions?
I believe you can use the Collection.observe on the server side to 'observe' events on the Collection as clients are inserting, updating, removing, etc... That might be a start if you are focused on Collections alone. I used it like a sort of server side event loop to watch for collection changes.
When a user clicks on something in a view try binding a Template Event to the View css selector and then calling a Meteor method which will notify the server of the event. See the examples of binding a key handler and/or button handlers to a Template.entry.event which then call a Meteor method notifying the server that something happened.
What about storing the progress in Session? You could do something like this:
Template.progress.value = function() {
return Session.get('progress');
}
Then, whenever you update the Session on the server, the client template will automatically get those changes.
Out of curiosity, how exactly are you performing asynchronous actions on the server? I'm still trying to figure that out.

Categories

Resources