How can I serialize backbone model into URL - javascript

I want to store state of a simple application in a model, and be able to generate URL containing full state of the application (i.e., serialized model). Is there a backbone-idiomatic way to provide such a feature?
Related:
BackboneJS model.url using collection.url
Backbone.js state management / view initialization based on url fragment

Backbone let's you serialize models to JSON but not to URL parameter syntax. You could stringify the JSON, url encode it, and then add it to the uRL ...
var json = yourModel.toJSON();
var jsonString = JSON.stringify(json);
var encoded = encodeURI(jsonString);
var url = 'www.example.com?model_json=' + jsonString;
... but I wouldn't recommend it. URL parameters were never designed to be used that way, and you can run in to lots of problems. One problem is character length limit. As this Stack Overflow answer explains, urls need to be limited to 2000 characters to be safe. Depending on what you put in your model, you could certainly exceed that without meaning to.
A much better approach would be to save the model somewhere that's designed to hold it, like on the server (that's exactly what the save method of a Backbone.Model is for, after all) or in local storage. Then, all you need to put in the URL is the model's ID, and you can use that ID to retrieve the data remotely/from local storage.

Related

What is the right way to pass array of objects with redirect?

I'm using node.js and I need to pass an array of objects with res.redirect(),
I tried with querystring but it's not a good idea because the array with too big and I could get Error 414 Request URI too long.
using connect-flash isn't a good way either, it's more useful for passing messages.
And I don't want to use req.app.locals for that.
Hope you can help me with any idea.
Assuming the client here is a browser that you want to just automatically follow the redirect and then inherit some new state when the server generates the page for that newly redirected URL, then here are some options:
If you already have a session established for the user, then you can store the data in the session, then include a single query parameter that tells the route handler for the page you're redirecting to to look in the session to get the relevant data.
You could also create a temporary server-side cache of data. Generate a random key (likely a timestamp plus a random number). Store the data in a server-side Map using that key. Then put the key into a query string on the redirect. Then, in the route handler for the new, redirected page, it will see the query string parameter and it can grab that key out of the query string and access the data from the server-side Map serving as a temporary cache (and probably remove it from the cache too). This scheme works in a session-less environment.
You then need some scheme for cleaning up unused data from the cache so it doesn't accumulate. Probably what makes sense it to timestamp the data and then have a setInterval() timer that just removes things from the Map if their timestamp is older than xx minutes.
If the request is an Ajax call rather than a regular browser page request, then you don't need to use a redirect at all. You can just return the content that they would have gotten if they then followed your redirect. Then, you don't have to invent a temporary place to store the data. You can just use the data to generate the desired page and return it.
Store the data as session data and serve it back up to them when they land on the landing page.
Another way would be to have the client request the data asynchronously once the redirect has been performed.

Keeping a global value in the next page [duplicate]

I want to send some data from one HTML page to another. I am sending the data through the query parameters like http://localhost/project/index.html?status=exist. The problem with this method is that data remains in the URL. Is there any other method to send the data across HTML pages using JavaScript or jquery.
why don't you store your values in HTML5 storage objects such as sessionStorage or localStorage, visit HTML5 Storage Doc to get more details. Using this you can store intermediate values temporarily/permanently locally and then access your values later.
To store values for a session:
sessionStorage.setItem('label', 'value')
sessionStorage.getItem('label')
or more permanently:
localStorage.setItem('label', 'value')
localStorage.getItem('label')
So you can store (temporarily) form data between multiple pages using HTML5 storage objects which you can even retain after reload..
I know this is an old post, but figured I'd share my two cents. #Neji is correct in that you can use sessionStorage.getItem('label'), and sessionStorage.setItem('label', 'value') (although he had the setItem parameters backwards, not a big deal). I much more prefer the following, I think it's more succinct:
var val = sessionStorage.myValue
in place of getItem and
sessionStorage.myValue = 'value'
in place of setItem.
Also, it should be noted that in order to store JavaScript objects, they must be stringified to set them, and parsed to get them, like so:
sessionStorage.myObject = JSON.stringify(myObject); //will set object to the stringified myObject
var myObject = JSON.parse(sessionStorage.myObject); //will parse JSON string back to object
The reason is that sessionStorage stores everything as a string, so if you just say sessionStorage.object = myObject all you get is [object Object], which doesn't help you too much.
possibly if you want to just transfer data to be used by JavaScript then you can use Hash Tags
like this
http://localhost/project/index.html#exist
so once when you are done retriving the data show the message and change the
window.location.hash to a suitable value.. now whenever you ll refresh the page the hashtag wont be present
NOTE: when you will use this instead ot query strings the data being sent cannot be retrived/read by the server
Well, you can actually send data via JavaScript - but you should know that this is the #1 exploit source in web pages as it's XSS :)
I personally would suggest to use an HTML formular instead and modify the javascript data on the server side.
But if you want to share between two pages (I assume they are not both on localhost, because that won't make sense to share between two both-backend-driven pages) you will need to specify the CORS headers to allow the browser to send data to the whitelisted domains.
These two links might help you, it shows the example via Node backend, but you get the point how it works:
Link 1
And, of course, the CORS spec:
Link 2
~Cheers

Alternative to passing Data to JavaScript from PHP?

I have a fairly large Application and I'm currently trying to find a way around having to pass Data from PHP (User Tokens for 3rd Party API's and such) through the DOM. Currently I use data-* attributes on a single element and parse the Data from that, but it's pretty messy.
I've considered just making the contents of the element encoded JSON with all the config in, which would greatly improve the structure and effectiveness, but at the same time storing sensitive information in the DOM isn't ideal or secure whatsoever.
Getting the data via AJAX is also not so feasible, as the Application requires this information all the time, on any page - so running an AJAX request on every page load before allowing user input or control will be a pain for users and add load to my server.
Something I've considered is having an initial request for information, storing it in the Cache/localStorage along with a checksum of the data, and include the checksum for the up-to-date data in the DOM. So on every page load it'll compare the checksums and if they are different (JavaScript has out-of-date data stored in Cache/localStorage), it'll send another request.
I'd rather not have to go down this route, and I'd like to know if there are any better methods that you can think of. I can't find any alternative methods in other questions/Google, so any help is appreciated.
You could also create a php file and put the header as type javascript. Request this file as a normal javascript file. <script src="config.js.php"></script> (considering the filename is config.js.php) You can structure your javascript code and simply assign values dynamically.
For security, especially if login is required, this file can only be returned once the user is logged in or something. Otherwise you simply return a blank file.
You could also just emit the json you need in your template and assign it to a javascript global.
This would be especially easy if you were using a templating system that supports inheritance like twig. You could then do something like this in the base template for your application:
<script>
MyApp = {};
MyApp.cfg = {{cfg | tojson | safe}};
</script>
where cfg is a php dictionary in the templating context. Those filters aren't twig specific, but there to give you an idea.
It wouldn't be safe if you were storing sensitive information, but it would be easier than storing the info in local storage,

Using Breezejs generate query string

I have a custom Odata endpoint which gets it filter via a post from the body and not the query string. At the moment all of the queries are hand coded and then fed in to the post.
I was wondering if anyone knows if I can use Breezejs just to create the query I need.
Cheers
According to the "OData AJAX" section in Controlling AJAX you'll need to make changes to your copy of data.js so that POST is used instead of GET.
If you don't care to have breeze load the data and just want to use the EntityQuery syntax to build queries you could try getting an instance of the breeze odata uriBuilder and call the buildUri method to convert the EntityQuery to an odata uri. Assuming that works, it would be a matter of grabbing the querystring component of the uri to use in your POST body.
var interfaceRegistry = breeze.config.interfaceRegistry,
uriBuilderInterface = interfaceRegistry.uriBuilder,
uriBuilderCtor = uriBuilderInterface.getImpl('odata').ctor,
uriBuilder = new uriBuilderCtor(),
uri = uriBuilder.buildUri(entityQuery, metadataStore);
There might be a better/simpler way of doing this... maybe by grabbing the uriBuilder from a breeze odata dataService instance. I don't think this is part of breeze's supported/documented public api but it sounds like it would make a nice feature suggestion to post on the user voice site.

Setting Backbone Marionette model via Global Object

In a Backbone.Marionette application I'm building, we have an authentication which returns a user object, which we in turn stash at App.User (so it's not truly global).
The problem I'm having is that I don't want to make a call to an API endpoint to access the various properties of the returned user object. The specific use case I'm working through right now is that the returned user object contains data about which modules in the app the user is permitted to access (no worries about security, we've clarified that it's OK that the user can spoof a var in their console to gain access to the UI, the services layer will prevent their actions in such an area from being meaningful).
My goal is to avoid a scenario where every time I need access to users.appAccess (a hypothetical array that lists the modules I can access) in order to instantiate it as a model I have to call out to a URL / API endpoint by declaring it in the collection's definition like this:
Entities.Access = Backbone.Collection.extend({
url: 'http://example.com/users/:id/access/',
}
});
Removing the url property from the above code throws an error, and I can pass it a function which returns empty but this doesn't play nice with
var access = new Entities.Access()
access.fetch();
when attempting to pass the fetched collection to a Marionette CollectionView. Should I simply avoid using the fetch() method and keep it otherwise a typical (albeit hack-ish) Backbone collection definition?
Backbone allows you to populate a Backbone collection either as you have (with an empty constructor) or with a collection of data. It sounds like you've already got the data stored in the User object, and you want to push this information to the Entities.Access collection.
var access = new Entities.Access(user.access);
I'm with you, this feels a bit like a hack, but since Backbone doesn't support this nativly there isn't much else you can do. Have a look at Backbone-Relational or supermodel.js. These projects provide better forms of model nesting than the default implementation.

Categories

Resources