Ember.js find with plain object is not working - javascript

I use Ember.js to get items like this:
App.MyData.find()
And to get item like this:
App.MyData.find(itemId)
And then I use filter and return it in model function like this:
App.MyRoute = Ember.Route.extend({
model: function() {
return App.MyData.find().filter(function(a)
{
return a.get('desc') != null;
});
}
});
And it's working just fine.
Now I wanted to pass another parameter to underlying PHP script returning items. So I used "Querying For Records desc":
"If you provide a plain object as the second argument to find, Ember Data will make a GET request with the object serialized as query params. This method returns DS.PromiseArray in the same way as find with no second argument."
According to the documentation it should behave the same way like find with no plain object argument.
But it does not. My view is not displaying anymore.
I checked GET request. It returns exactly the same data.
I have no errors in JS.
What to do to pass parameter to PHP while getting items in a way it will work?

As you can see in this jsbin it does work. So if it doesn't work for you you either have a really old version or you're doing something else wrong.
I use this to get the model:
App.IndexRoute = Ember.Route.extend({
model: function() {
return this.store.find('thing', { beer: 'heineken' });
}
});
and that results in this request: GET /things?beer=heineken".

Related

How to get variables out of a get odata call method

What is the best way to get variables out of a get odata call. I have this code in a method where i want to work with the variable 'id', which i am getting with the odata call. I tried already callbacks but i cant get the right way. Do you have a solution for this? I tried also to put the call in an extra function, but then i get the problem that by return variable is undefined i a cant access it.
Update / additional:
I have a method where i am doing some odata updates and inserts. in my code below i am getting a id. this id i need in the next step for another odata update as parameter. My problem is that i cant work with the var id in the next steps of my code, because its only accessable in the oModel {} section.
oModel.read("/ZDEMA_LENDINGS2Set", {
urlParameters: {
"$select": "Id",
"$top": 1
},
success: function(oData, oResponse) {
console.log("Data", oData);
console.log("Response", oResponse);
var id = oData.results[0].Id;
},
error: function(oError) {
console.log("Error", oError);
}
}
Since this an UI5 app, I suggest using a local JSON Model and set the value as property.
this.getView().getModel('myLocalModel').setProperty("lendingId", oData.results[0].Id)
This has the advantage that you can use the two way databinding and or change listeners.
Alternative approach is to fire an event on the event bus.

Factory returning same value

I am trying to get songs from soundcloud, I am using some input to set value and send it to my factory to get all the related list of songs and display it.
The issue is the the first time all works correctly, but when I am trying to input new values I am getting same results as first time.
My code looks like:
.controller('DashCtrl', function ($scope, SongsService) {
$scope.formData = {};
$scope.searchSong = function () {
SongsService.setData($scope.formData.songName);
};
UPDATE
the factory :
.factory('SongsService', function ($rootScope) {
var List = {};
List.setData = function (tracks) {
var page_size = 6;
SC.get('/tracks', {limit: page_size, linked_partitioning: 1}, function (tracks) {
// page through results, 100 at a time
List = tracks;
$rootScope.$broadcast('event:ItemsReceived');
});
};
List.getItems = function () {
return List;
};
return List;
}).value('version', '0.1');
Thanks for help!
It's hard to tell without a plunkr reproducing the issue and showing all your relevant code, but I think your problem is that you're overwriting the List variable in the async answer, and this List (I assume) is the object you originally returned from your factory.
I see two noteworthy concepts here:
the fact that angular factories are effectively singletons
and that javascript objects are passed by reference-by-value (see call-by-sharing, or one of many stackoverflow discussions).
An angular factory is a singleton, meaning the factory function will only be called once, before the first injection, and every controller it's injected into will work with the same object reference it returned. If you overwrite this object reference, well, the previous value (which the controller has) is still a reference to the original object.
Edit: In fact, by overwriting List you're creating a new object which doesn't even have a setData method anymore!
You probably want to make List private to SongsService, and return a more complex object from the factory that captures List in a closure, and offers some public getter/setter methods for it. (If you insist on replacing the contents of the returned List variable, empty the object and extend it with the new properties - including this method again. But this is much more work, and not a nice solution.)
In Angular Service constructors and Factory methods are singleton objects. You need to return a method that you can call. Your code examples are incomplete so it is hard to tell what is going on. What is returned by your factory method, the List object?
If so, when the first call is completed, it overwrites the List object so that the setData method can't be called a second time. What is the SC object, I can not see in your example how you are injecting it. You probably want to fix that too.
Consider this possible solution.
Service
Songs.$inject = ['$http'];
function Songs($http) {
this.$http = $http;
}
Songs.prototype.getSongs = function(searchTerm) {
return this.$http.get('http://someendpoint/songs', {searchTerm: searchTerm});
}
service('songs', Songs);
Controller
DashController.$inect = ['songs'];
functionDashController(songs) {
this.songs = songs;
this.results = [];
}
DashController.prototype.searchSongs = function(searchTerm) {
var self = this;
this.songs.getSongs(searchTerm).then(function(results) {
this.results = results;
});
}
controller('DashController', DashController);
This is example uses the best practice controllerAs syntax explained here: http://toddmotto.com/digging-into-angulars-controller-as-syntax/
I found the issue,
I got same results all the time because I didnt use cooreclty the api of soundcloud, I didnt send the title on the api... also you are correct, I should not set the list as empty..I should set some value to the list...

Backbone.js model.fetch when server data is empty

I have an app where we are using model.fetch() to pull JSON from the server, and we have this as our render function that fires when the model changes:
if(_.isUndefined(this.model.get("id_number"))){
this.template = initialTemplate;
} else if(this.model.get("id_number") == 0) {
this.template = templateA;
} else {
this.template = templateB;
}
return BaseView.prototype.render.call(this);
On pageload, we don't do model.fetch() yet and get the initialTemplate. When a user changes an input, we fetch and get new model data that can have an ID of 0 or something else.
Now there is also a chance the server JSON might change to an empty {} and if so we need to revert to showing the initialTemplate. The problem is it appears that if that's the case, model.fetch() doesn't return anything and nothing changes. Same thing if id_number is undefined. (It does work if it's null.)
Is there a solution so Backbone will fetch an empty data set?
The solution for this was something Stephen mentioned: a success function. I added this to the model.fetch() function:
success: function(model, response /*jshint unused: false */) {
if (_.isEmpty(response)) {
view.model.set("id_number", undefined);
}
},...
FYI to anyone who uses this in the future: Backbone won't let you pass only response to the function because it expects model first. You can pass model and not use it, but you'll need the comment above to pass JSHint.
Set defaults in your model
Here is documentation.
http://backbonejs.org/#Model-defaults

Backbone & working with non-JSON data

I have a static file that's just one date-time per line, e.g.:
2014-03-14T16:32
2014-03-15T13:04
2014-03-16T06:44
...
I want to use that as a read-only data source for a backbone collection. Obviously that's not in the expected format. I thought I could just use the parse method on my collection to just convert it into a proper array of objects. Unfortunately, that doesn't seem to be working.
First, if I don't override fetch, the parse method never gets called -- it goes into the error handler, though it's unlcear exactly why -- it's not actually throwing any errors. I'm guessing that's because it's expecting a different response type or something?
Second, if I override both the fetch & parse methods thus:
var MyColl = Backbone.Collection.extend({
model: MyModel,
url: 'date-list.txt',
parse: function(data) {
var result = _(data.split("\n")).compact().map(function(item, i) {
return { theDate: item, globalIndex: i };
});
return result;
},
fetch: function() {
$.get(this.url, this.parse);
}
});
it correctly goes into parse, and parse seems to build a valid object, but my collection has 0 models after the whole operation...
I suppose the collection is winding up empty because when I call parse, it's not part of the expected flow any more so nothing is done with the result. Any other ideas about how I can make fetch properly handle what the server is returning?
Obviously, I could make the server return JSON, or I could use my own fetching function outside of backbone, but I'm hoping there's a way to avoid those ideas.
I believe the default fetch method assumes you will be returning JSON from the endpoint, which the collection will then instantiate a new model for each object in the array from the JSON data.
With your current override, you just need to just build an array of Backbone models in your parse method:
parse: function(data) {
var model = this.model;
var result = _(data.split("\n")).compact().map(function(item, i) {
return new model({ theDate: item, globalIndex: i });
});
return result;
},
It looks like you are not passing correct function to $.get, or, to be more precise, correct function but not bound to specific object instance. One idea is to try this:
$.get(this.url, _.bind(this.parse, this));
But now, as you said, nothing is done with the result of parse method, so you can add elements to collection like this:
parse: function(data) {
var result = _(data.split("\n")).compact().map(function(item, i) {
return { theDate: item, globalIndex: i };
});
this.set(result);
}

How to get a model attribute after fetch operation

I am a newbie in backbone . I wanted to know when i do the following operation how i can get the model fetched values.
For example if i do something like following
this.model.fetch();
and i want to get a value for example
this.model.get("VALUE");
How i can make sure i get the right value which is fetched right now from the server. I am trying to do something like following but ofcourse this.model is not recognized inside the complete block.
this.model.fetch().complete(function(){
window.localStorage.setItem("VALUE", this.model.get("VALUE"));
});
I am stuck here. Does anybody have any ideas.
Well, I see two options: 1. just get rid of the complete block and use the functions separately.
this.model.fetch();
var value = this.model.get('value');
//or, if you want all of the values
// var values = this.model.toJSON();
// values.value -> the specific value
And I'm not very experienced with local storage, but why are you fetching a value and then setting it to local storage?
Or, 2. You could put your inner statements in a function, and bind it to the this:
initialize: function () {
_.bind('setItem', this);
},
setItem: function() {
// assuming this code works
window.localStorage.setItem("VALUE", this.model.get("VALUE"));
}
// elsewhere, and not familiar with complete, so I'm not certain how this works
this.model.fetch().complete(setItem);

Categories

Resources