Access JSON data from Backbone Router - javascript

In my bb router I get some JSON data
$.ajax({
url: "js/projects.json",
success: function(projects) {
database.projects = projects;
var variables = {};
var niz = new Array();
var param = "Client"
$.each(projects, function()
{
if (!variables[this[param]])
variables[this[param]] = [];
variables[this[param]].push(this);
});
for(var d in variables) {
niz.push(d);
var number_of_clients = niz.length;
}
console.log(number_of_clients);
Backbone.history.start();
}
});
Now I wanna access this "projects" from one of my Views and to some stuff with that data , I know I can do the same thing again like here , but its duplicating code , is there any way to get this data in View ? I tried a few things but with no success , I allways get the undefined

You can attach your data to the window (window.projects = projects), then you can access it from everywhere. But I recomend you to use the ajax tools from Backbone, it's much easier and less messy.

Honestly, your question seems very suspicious design-wise. :)
Ajax calls should be made in models using the fetch function, not in a router, and not using jquery directly.
So I would advise you to redesign your app unless you have a strong reason not to do so.

Related

java script - using parse.com query with angular ng-repeat

I make a query from parse.com angd get and array of 2 object. Now I want to user ng-reapet('phone in phones') , so I need to convert it to json. I didn't suucess to do it. for some reason, it doesnt see the result as a json.
var Project = Parse.Object.extend("Project");
var query = new Parse.Query(Project);
query.find({
success: function (results) {
var allProjects = [];
for (var i = 0; i < results.length; i++) {
allProjects.push(results[i].toJSON());
}
$scope.phones = allProjects;
//i also tried this : $scope.phones = JSON.stringify(allProjects);
},
error: function (error) {
alert("Error: " + error.code + " " + error.message);
}
});
Thanks
Not sure if you already figured this out, but I was having a similar issue and found your post. I'm not sure what your HTML looks like, but I ended up using the Parse.Object's get method in my repeater like so:
<ul ng-repeat="list in lists">
<li>
<a ng-href="#/lists/{{list.id}}">{{list.get('title')}}</a>
</li>
</ul>
I also looked into using promises so that the Parse query success callback actually updates the view when you set $scope.phones to the query result. My code is similar to yours but my object is List instead of Project. Here is what mine looks like:
// Define your Parse object
var List = Parse.Object.extend('List');
// Define a function that runs your Parse query. Use an angular promise so that
// the view updates when you set your $scope var equal to the query result
function getList() {
var deferred = $q.defer();
var query = new Parse.Query(List);
query.find({
success: function(results) {
deferred.resolve(results);
},
error: function(error) {
deferred.reject(error.message);
}
});
return deferred.promise;
}
// Call the getList function on load
var promise = getLists();
promise.then(function(lists) {
$scope.lists = lists;
});
So basically, it isn't that Angular doesn't see the response right. You shouldn't have to modify the result from Parse in any way. It's just that you need to use the Parse.Object get method like you would if you were accessing properties of the object, and make sure that you are using a promise so that Angular accesses your query result as it should in the view.
Do not use .get function on Parse in you angular code, its not working any more, plus its not a good idea to change your angular code because your object is three level nested and need a get method.
The proper way is to extend the object and then map the values back to whatever items you need in that class.
Then you can bind in normally to ng-repeat without changing your html code specifically for Parse.
var Game = Parse.Object.extend("Game");
var query = new Parse.Query(Game);
query.find({
success: function(results) {
$scope.$apply(function() {
$scope.games = results.map(function(obj) {
return {points: obj.get("points"), gameDate: obj.get("gameDate"), parseObject: obj};
});
});
},
error: function(error) {
console.log(error);
}
There may be better tools , frameworks to use.
line 188 is the fetch. It automatically loads json for the model into the collection defined at line 47.
Looping over entries in the result from the query on parse is all automated in the framework so that you can save yourself tons of time by learning a relevant framework ( ie backbone ). On backbone/parse you focus on business logic , not manipulating network io and query structures.
'phone in phones' from your question may just be a nested model or nested collection which IMO can be handled by more advanced manipulation of the basic backbone framework.

Confused about complex class structure and Knockout

Been getting into Knockout and and slowly getting used to it. Trying to use it in a new project, but am having a hard time getting things lined up to work. While I understand and can do simple examples (simple form with text boxes bound to ko.observables, or a table or list bound to a ko.observableArray), I can't get the syntax right for a combination, especially if I want to convert the data to JSON format in order to transmit it, via a webservice, to be saved into a database.
Basically it's a data entry form, with some text entry boxes, then a list of items (think company information + a list of it's employees).
I have a sample Fiddle here: http://jsfiddle.net/rhzu6/
In the saveData function, I just don't know what to do to get the data packaged. Doing ko.toJS(self) just shows "Object".
I tried defining the data as objects, but quickly got lost:
function Company(CompanyName, ZipCode) {
var self = this;
self.ZipCode = ko.observable(ZipCode);
self.CompanyName = ko.observable(CompanyName );
self.Employees = ko.observableArray();
}
function Employee(FirstName, LastNameB) {
var self = this;
self.FirstName = ko.observable(FirstName);
self.LastName = ko.observable(LastName);
}
Then the ViewModel looked like:
function viewModel() {
var self = this;
self.Company = ko.observable(); // company?
self.Employees = ko.observableArray(); // ?
}
But ran into the same issue. And also had binding problems - data-bind:"value: CompanyName" threw an exception saying it didn't know what CompanyName was...
Color me stumped. I'm sure it's something easy that I'm just missing.
Any and all help would be appreciated!
Thanks
You are looking for ko.toJSON which will first call ko.toJS on your ViewModel and afterwards JSON.stringify.
ko.toJS will convert your knockout model to a simple JavaScript object, hence replacing all observables etc. with their respective values.
I updated your Fiddle to demonstrate.
For more info, take a look at this post from Ryan Niemeyers blog.
An alternative is to make use of ko.utils.postJson:
ko.utils.postJson(location.href, {model: ko.toJS(viewModel) });
Notice the ko.toJS again.
It looks to me as if you (semantically) want to submit a form. Therefore, I think that you should use the submit binding. The biggest benefit is that you listen to the submit event, which allows submit by other means, such as Ctrl+Enter or any other keyboard combination you want.
Here is an example on how that submitEvent handler could look like. Note that it uses ko.mapper, which is a great way to create a viewModel from any JS/JSON-object you want. Typically, you would have
[backend model] -> serialization -> [JS/JSON-ojbect] -> ko.mapper.fromJSON(obj) -> knockout wired viewModel.
viewModel.submitEvent = function () {
if (viewModel.isValid()) { //if you are using knockout validate
$.ajax(
{
url: '/MyBackend/Add',
contentType: 'application/json',
type: 'POST',
data: ko.mapping.toJSON(viewModel.entityToValidateOnBackend),
success: function (result) {
ko.mapping.fromJSON(result, viewModel);
}
}
);
}
};
Good luck!

spine.js populate model instances at start up

Absolute beginner here. I want to load data into models as soon as the page loads.
Before anything else is executed. At the moment I have this code.
// Model code
var Portfolio = Spine.Model.sub({});
Portfolio.configure("Portfolio")
Portfolio.extend({
populate: function(values){
for(var i in values[0]){
// add attributes to Model
this.attributes.push(i);
}
for(var j = 0; j < values.length; j++ ){
var tmpInst = this.create(values[j]);
tmpInst.save();
}
}
});
// app controller code
$(function(){
var App =Spine.Controller.sub({
init: function(){
jQuery.getJSON("../xml/data.json",
function(result){
Portfolio.populate(result['content']);
}
).complete(function(result) {
// do other stuff
});
}
})
var app = new App();
});
So when the page has finished loading the controller init function is called, which retrieves the json data and passes it to the Model which parses it and creates the individual instances.
Am I doing this wrong? I have seen Fetch function in the documentation but with no example of how it works.
You might want to use Spine's framework to do this:
Instead of firing your own jQuery.getJSON(), include Spine.Ajax in your Model.
Portfolio.extend(Spine.Model.Ajax);
Set the Spine.Model.host to your server
Add url attribute/method to your Portfolio object to something like 'xml/data.json'
Call Portfolio.fetch()
Override Portfolio.fetch() function to extract just the node of array data or whatever initialization you had in mind just like the configure. If I am not mistaken, fetch() will load the objects and set all the attributes provided in the JSON even if they are not configured in Model #configure call

Backbone.js relations

I'm having an issue wrapping my head around relational models in Backbone. I've just started using it and I'm tasked with a fairly large application.
The main issue I'm having is that I have a model that should contain a collection.
This is what I have to work with:
modelA
id: _id
url: api/model/:modelA_id
nested:
url: api/:modelA_id/nest
I think I'm making it a bigger deal than I need to, but I just can't seem to wrap my head around how to set this up.
Any help will be most appreciated.
The biggest thing to wrap your head around with Backbone is how to properly use events to deal with basically everything in the app. The other big thing to understand is that there are probably 5 different ways to attack a problem, where none of them are better/worse than the other.
Given that loose structure you've provided, I would do something like:
var YourApp = {
Models : {}
Collections : {}
Views : {}
};
YourApp.Models.First = Backbone.Model.extend({
initialize : function(){
var nestedCollection;
this.url = 'api/model/' + this.id;
nestedCollection = new Backbone.Collection({
url : this.url + '/nest'
});
this.set('nested', nestedCollection);
}
});
new YourApp.Models.First({
id : 23
});

Grails - Calling controller and rendering template from Javascript method

How do I map calls to a Grails controller from a Javascript method? I see a method using PHP, but not with grails:
function getSelected(checkList)
{
var idList = new Array();
var loopCounter = 0;
//find all the checked checkboxes
jQuery("input[name=" + checkList + "]:checked").each
(
function()
{
//fill the array with the values
idList[loopCounter] = jQuery(this).val();
loopCounter += 1;
}
);
//call here
}
Edit:
${remoteFunction(controller:"person", action:"runThroughAll", params:"[ids:idList]")}
So, I feel like there are sort of two things you're asking here. I'm going to tackle them both. First, how do you get the URL right for a call to a grails controller from JavaScript? In my GSP page (I do it in my main layout but whatever), I like to do this little trick:
<script>
myapp.url.root = "<g:resource dir='' file='' />" + "/";
</script>
That will give you the base root of your app wherever it's deployed. Then, you can build your URLs in JavaScript:
myurl = myapp.url.root + "path/to/controller"
Then make a jQuery ajax call using that url.
Then make sure that your controller is set up to respond to whatever URL pattern you've just expressed.
The second question appears to be, "how can I send back an HTML fragment"?
Inside the controller itself, take the parameters from the request, use it to figure out whatever you need, then render the gsp, passing in the model you've created. It will look something like this:
def show() {
def data = [hypothesis : metadataService.getHypothesis(params.id) as JSON]
render(view:"create", model:data)
}
Then in jQuery, your success handler will get as an argument the returned response, which you can then inspect/manipulate/add to the dom.
Hopefully all that made sense. If I glossed over something or didn't answer the question you were asking, let me know.
EDIT: For future reference, here is the javascript method rewritten which we arrived at in chat:
function getSelected(checkList){
var idList = $("input[name='" + checkList + "']:checked").map(function(){ return $(this).val(); });
$.ajax({
url: "/path/to/controller",
type:"POST",
data:{ids:JSON.stringify(idList)}
success:mySuccessFunction
});
}

Categories