Backbone Model Fetch() is adding extra parameters to url - javascript

I've been going at this for a solid hour, and I have a feeling it might be something simple. I'm doing a basic model fetch with backbone.js with the code below.
var Document = Backbone.Model.extend({
urlRoot: "/Package/Documents/GetDocumentById/"
});
mydocument = new Document({id: "3978204"});
mydocument.fetch()
I would expect the above code to make a call to the following url
localhost:3000/Package/Documents/GetDocumentById/3978204
But instead it is adding an extra parameter to the query which is blowing up my method.
localhost:3000/Package/Documents/GetDocumentById/3978204?_=1318548585841
I have no idea how ?_=1318548585841 get rid of the extra parameter.
Any help would be apperciated.

Take a look at this related question. This is a cache-buster added by jQuery.ajax(), which Backbone uses in the background.
I believe you can remove this by passing cache:true as an option to fetch() (which gets passed to $.ajax()):
mydocument.fetch({ cache: true });
If that works but you don't want to do it every time, you could set it globally with jQuery.ajaxSetup().

Related

How to redirect to a play framework url from within javascript without hard-coding the url

I need to do something seemingly quite simple.
In the same way that I can, from my scala.html file, create a link to another url, /entry, I need to do that from a javascript file.
i.e., from the scala.html:
<div class="footer">
<a href='#routes.Application.index()'>Home</a>
</div>
from my javascript event:
function() myEvent {
window.location="#routes.Application.entry()"; // DOESN'T WORK!
}
For routing from javascript, I've already had to setup my javascript routes for some ajax work I've already had to do.
My ajax work was calling a method 'findPersons()' so in my Application.java file, I had already:
public Result jsRoutes()
{
response().setContentType("text/javascript");
return ok(Routes.javascriptRouter( "appRoutes",
routes.javascript.Application.findPersons()));
}
Because I want to be able to redirect to my GET entry() method, I modified it to look like this:
public Result jsRoutes()
{
response().setContentType("text/javascript");
return ok(Routes.javascriptRouter( "appRoutes",
routes.javascript.Application.findPersons(),
routes.javascript.Application.entry()));
}
Additionally I have these in my routes file:
GET /entry controllers.Application.entry()
POST /findPersons controllers.Application.findPersons()
When I am invoking my findPersons method, it is really nice and simple.
It looks like this:
appRoutes.controllers.Application.findPersons().ajax({
data: {
personIdentifier : personIdentifier,
surname : surname,
givenNames : givenNames
},
success : processDBQuery
});
For my simple redirect, I would like to be able to maintain the same loose coupling between my html/javascript code and the urls, as I can the ajax call above.
My redirect needs to occur on an event. Therefore, the easiest and quickest solution would have been simple to write:
function() myEvent {
window.location="/entry";
}
However, then I would be hard-coding the URL (which I have managed to avoid for my ajax call above), no longer maintaining that loose coupling I would so much like to have.
However, I see no examples in the documentation, and from what I have in the generated javascript (for my routes) there is no chance.
Is there any way to achieve what I am after?
thanks for reading!
p.s., I should add; I guess I have also thought of the possibility of using the ajax call that is generated, I guess I can probably fetch the page I want... and there is probably a means of replacing the current document with the entire content of the fetched page. but that just sounds bad.... wrong...
or not?
I was rather hoping for a substitution, as is done in my html
i.e, my link as shown above is generated to look like this:
<div class="footer">
<a href='/'>Home</a>
</div>
In the same way, I hoped there was some means of substitution in the javascript, so that the event function above ends up in being massaged into looking like this:
function() myEvent {
window.location="/entry";
}
Jacques, from the above comments, helped me to realize a work-around.
From within my "assets located" javascript file, I can still refer to page/template located javascript.
Own-file/assets located javascript doesn't seem to be transformed how I expected.
However, Page/template located javascript is transformed exactly how I require.
I can refer to a template located javascript function from my assets located javascript.
This means, I have a little work-around of one extra little function inside the template which does the redirection for me.
i.e.,
myJavascript.js:
function personResultsListClickHandler(personId) {
var fpersonId = personId;
return function() {
window.alert("hello! " + fpersonId);
affectRedirect();
};
}
myTemplate.scala.html
#main("person lookup") {
<script type="text/javascript">
function affectRedirect(){
window.location="#routes.Application.entry()";
} // Need this here so it will be transformed.
// asset located javascript doesn't seem to get transformed like javascript here in template! :(...
</script>
Another possibility is the fact that the Javascript object retrieved by calling:
appRoutes.controllers.Application.entry()
contains a url member. This url member is exactly what I can use to assign to window.location. However, it looks a bit unofficial.. in terms of
1. the member not being documented
2. not sure if the url member will exist in the future
3. the generated javascript is constructing an object dealing with ajax... and i'm just grabbing the URL member from it... it just feels... like a hack.
But i've tested this, and it works. See code below:
function patientResultsListClickHandler(personId) {
var fpersonId = personId;
return function() {
window.location=appRoutes.controllers.Application.entry(personId).url;
// window.location="/entry/" + fpersonId; // the sort of hard-coding of URL that
}; // I wanted to avoid, but don't seem able to.
}
Does anyone else have a better solution?

restangular save ignores changes to restangular object

I'm trying to call save on a restangularized object, but the save method is completely ignoring any changes made to the object, it seems to have bound the original unmodified object.
When I run this in the debugger I see that when my saveSkill method (see below) is entered right before I call save on it the skill object will reflect the changes I made to it's name and description fields. If I then do a "step into" I go into Restangular.save method. However, the 'this' variable within the restangular.save method has my old skill, with the name and description equal to whatever they were when loaded. It's ignoring the changes I made to my skill.
The only way I could see this happening is if someone called bind on the save, though I can't why rectangular would do that? My only guess is it's due to my calling $object, but I can't find much in way of documentation to confirm this.
I'm afraid I can't copy and paste, all my code examples are typed by hand so forgive any obvious syntax issues as typos. I don't know who much I need to describe so here is the shortened version, I can retype more if needed:
state('skill.detail', {
url: '/:id',
data: {pageTitle: 'Skill Detail'},
tempalte: 'template.tpl.html'
controller: 'SkillFormController',
resolve: {
isCreate: (function(){ return false;},
skill: function(SkillService, $stateParams){
return SkillService.get($stateParams.id, {"$expand": "people"}).$object;
},
});
my SkillService looks like this:
angular.module('project.skill').('SkillService', ['Restangular, function(Retangular) {
var route="skills";
var SkillService= Restangular.all(route);
SkillService.restangularize= function(element, parent) {
var skill=Restangular.restangluarizeElement(parent, elment, route);
return skill;
};
return SkillService;
}];
Inside of my template.tpl.html I have your standard text boxes bound to name and description, and a save button. The save button calls saveSkill(skill) of my SkillFormController which looks like this:
$scope.saveSkill=function(skill) {
skill.save().then(function returnedSkill) {
toaster.pop('success', "YES!", returnedSkill.name + " saved.");
...(other irrelevant stuff)
};
If it matters I have an addElementTransformer hook that runs a method calling skilll.addRestangularMethod() to add a getPeople method to all skill objects. I don't include the code since I doubt it's relevant, but if needed to I can elaborate on it.
I got this to work, though I honestly still don't know entirely why it works I know the fix I used.
First, as stated in comments restangular does bind all of it's methods to the original restangularizedObject. This usually works since it's simply aliasing the restangularied object, so long as you use that object your modifications will work.
This can be an issue with Restangular.copy() vs angular.copy. Restangualar.copy() makes sure to restangularize the copied object properly, rebinding restangualr methods to the new copy objects. If you call only Angular.copy() instead of Restangualar.copy() you will get results like mine above.
However, I was not doing any copy of the object (okay, I saved a master copy to revert to if cancel was hit, but that used Restangular.copy() and besides which wasn't being used in my simple save scenario).
As far as I can tell my problem was using the .$object call on the restangular promise. I walked through restangular enough to see it was doing some extra logic restangularizing methods after a promise returns, but I didn't get to the point of following the $object's logic. However, replacing the $object call with a then() function that did nothing but save the returned result has fixed my issues. If someone can explain how I would love to update this question, but I can't justify using work time to try to further hunt down a fixed problem even if I really would like to understand the cause better.

knockout.js, breeze and dynatree/fancytree

This is really tricky to get my head around as I'm not used to this style of programming/data management.
All I'm trying to do at the moment is pass a json object returned via breeze into a dynatree or fancytree.
The examples that exist online all assume that the tree will do the ajax call via "initajax" or that some weirdly convoluted custom binding handler is needed into which various objects are passed:
ko.bindingHandlers.dynatree = {
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
setTimeout(function () {
$(element).dynatree({
noLink: true, // noLink is required to 'unlock' the checkboxes
minExpandLevel: 2
})
// the timeout value shows the correct knockout bindings BEFORE dynatree kicks in.
}, 1000);
}
}
This all seems too complicated to me, surely? I already have the json object, I know that's working. If I use knockout to "foreach" bind it to some plain html then all data is displayed just fine. In my mind all I need to do is initialize the tree div and pass it the json object... It's just that I have no idea how to do that!
I've tried using the jsfiddle here: http://jsfiddle.net/Ebram/UhA3m/5/ but chrome developer tools complain about the element having no "dynatree" method when the custom binding handler fires. It's passing in a "ul" element and that could be the problem - surely it should be passing in the tree div, not the ul element?
Anyhow, if anyone could point me in the right direction I'd hugely appreciate it. As I'm using John Papa's SPA methodology, I'm also unsure as to where I would put any separate js initialization code as the underlying viewmodel isn't the right place for me to be doing a $(#tree).dynatree initialization type call, is it? I must admit I've not got my head around this yet.
I suppose all I'm looking for is something along the lines of "once the viewmodel for this view has finished loading and the knockout binding is being done, initialize the dynatree div and pass this json object to the tree" if that makes sense in pseudocode?
I can hopefully point you in the approximate right direction.
It seems dynatree can also take JSON from a file as well as an AJAX request. In this example Lazy Loading, if you look in the source code, there's:
// In real life we would call a URL on the server like this:
...
// .. but here we use a local file instead:
Storing your data in a file to get it in seems awfully wasteful. Now that we know it's a little flexible in what it gets, let's see where it uses the data and maybe we can get it to use a local variable instead. let see where it loads it
Looking in the dynatree source, there's a function associated with appendAjax. (line 1774 in my source.) A little short on time at the moment, but I'd find where it gets the JSON and what it does with it. Perhaps you can do the same thing outside or mod the handling of ajaxOptions to take a variable with the JSON.

Querying the DOM in Windows 8 Apps from within a method

I'm struggling with this even after reading the MSDN documentation and the following online guides:
Codefoster
Stephen Walter
I think my problem is easy to fix and that I just am thinking about something in the wrong way. Basically I am querying my web service and on success running the following method. I am then trying to bind the result to my listview. For now I am using a hardcoded value publicMembers.itemlistwhich has been declared at the top of the document just to make sure I can actually bind to the list before doing it with my query results. Ignore line 2 for now.
Success Method:
_lookUpSuccess: function xhrSucceed(Result) {
var response = JSON.parse(Result.responseText);
listView = document.querySelector("#termTest");
ui.setOptions(listView, {
itemDataSource: publicMembers.itemList,
itemTemplate: document.querySelector(".itemtemplate"),
})
},
Now, instead of using document.querySelector, I have also tried with WinJS.Utilities.id and WinJS.Utilities.query, neither of which worked either. This doesn't break my code and introduce an error but it doesn't bind to the listview either so I think I have an issue in querying the right DOM element. However exactly the same code does work if I add it to the top of the script, it is only when I place it in this method that it stops working.
EDIT: Also to clarify, when I debug publicMembers.itemList is storing the values I expect them to be.
Please point out if I have explained things poorly and I will try and improve my question.
Thanks.
I haven't used WinJS.UI.setOptions, but rather this other way of setting the data source. Can you see if it works?
_lookUpSuccess: function xhrSucceed(result) {
var response = JSON.parse(result.responseText);
listView = document.querySelector("#termTest");
listView.winControl.itemDataSource = publicMembers.itemList;
},
This would assume you're defining the itemTemplate as part of the data-win-options attribute of your ListView's HTML element. You could also probably just do listView.winControl.itemTemplate = document.querySelector(".itemtemplate") if you prefer to set it programmatically.

Monkey patch not firing. (Guess this Monkey cant punch ducks.)

I am trying to patch the JsonRest query method. Nothing I do seams to have an effect. Below I would expect the query method to no longer work and just write "monkey punching a duck." out to the console. But alas the entire app keeps on working ignoring my blatant attempt to break it. Do I need to patch a specific instance?
dojo.require("dojo.store.JsonRest");
(function(query, options){dojo.store.JsonRest.query=function(){console.info("monkey punching a duck.");};})();
aprStore = new dojo.store.JsonRest({"target":"/web/rest/apr/","idProperty":"ID"});
var sqry = "?nq=aquerytorun";
aprStore.query(sqry).then(function(result){});
The main goal is I want at the underlying xhrGet so I can attach a callback to the error property. The .query(function,function) is ignoring my error function passed in as the second parameter. http 302 is what is driving me nuts at the moment.
It's not 100% clear what you're trying to do, but I suspect you need to put your function on the prototype object of that JsonRest thing:
dojo.store.JsonRest.prototype.query = function() { ... };
Then instances made from that constructor will have access to your "query" function.

Categories

Resources