I am new to AngularJS, but have used Backbone for a while now.
I want to create a reusable restful api that I can pass the model name to so that I can use it for different models.
At the moment I have:
angular.module('healthplanApiServices', ['ngResource'])
.factory('Api', function($resource) {
return $resource(base_url + 'api/:object/:id', {
id : '#id', object : 'actions'
}, {
query : {
method : 'GET',
isArray : true,
callback : "JSON_CALLBACK"
},
save : {
method : '#id' ? 'PUT' : 'POST',
isArray : true,
callback : "JSON_CALLBACK"
}
});
});
... which sets the model as 'actions'. Then in my controller I use:
// get the collection
Api.query(function(r) {
$scope.actions = r;
});
$scope.toggleDone = function(a) {
a.done = !a.done;
//save an item
Api.save(a);
}
That's all fine, but how do I pass the model name ('actions' in this case) for each model type: e.g., instead of putting it in the factory function like so:
id : '#id', object : 'actions'
... but rather something more like:
var ActionApi = Api.setObject('actions');
ActionApi.query(function(r) {
$scope.actions = r;
});
UPDATE:
I just figured out a way. It may not be the best, but it does work. Any other suggestions would be welcome!
Just add the 'object' attribute to the model:
Api.query({object: 'actions'}, function(r) {
$scope.actions = r;
angular.forEach($scope.actions, function(a) {
a.object = 'actions' });
});
Api.save(a);// also works
You may want to try https://github.com/klederson/ModelCore ( ModelCore )
Its easy to model and structure and of course ... to use.
model.$find({ filter : "John" },{},true); //to find all with query parameters
model.$get(1); //to retreive the user with id 1
model.$save()
model.$deelte();
And so on.. checkout the documentation
Related
I am trying to call a API in onSync() and return payload so that I will get number of devices. Even the api is returning me the proper data I am unable to show the devices. Following is the code snippet.
app.onSync((body) => {
// TODO: Implement SYNC response
console.log('************** inside sync **************');
var payload = {
agentUserId:'123',
devices:[]
};
//Calling Discove Devices API
requestAPI('------ calling API ------')
.then(function(data){
let result = JSON.parse(data);
console.log('********** RESULT ********** '+util.inspect(result,{depth:null}));
var count = 0;
count = Object.keys(result.Devices).length;
console.log('********** DEVICE COUNT ********** '+count);
//forming payload json of devices
for(var i in result.Devices){
var item = result.Devices[i];
payload.devices.push({
"id" : item.ieee_address,
"type" : 'action.devices.types.OUTLET',
"traits" : ['action.devices.traits.OnOff'],
name : {
"defaultNames" : [item.mapped_load],
"name" : item.mapped_load,
"nicknames" : [item.mapped_load],
},
"willReportState" : false,
"deviceInfo" : {
"manufacturer" : 'some manufacturer',
"model" : 'Smart-Plug',
"hwVersion" : '1.0',
"swVersion" : '1.0.1',
},
});
}
}).catch(function(err){
console.log(err);
});
console.log('PAYLOAD %J ',payload); <----- it is always empty
return {
requestId: body.requestId,
payload: payload,
};
});
API is returning me correct value but the payload is always empty.
Please help. I am new to node.js and I dont know how to make async call.
You're using an asynchronous call to get devices, and you'll need to make sure you don't return data before your request is complete. You return the Promise to the function, so it will wait:
app.onSync((body) => {
return requestApi('...')
.then(data => {
return {
requestId: body.requestId,
payload: payload
}
})
})
I am using the OData model to read data. But it doesn't work. Check the code below:
getGuid: function(pernr) {
var self = this;
var url = "/PersonalDetailSet?$filter=Pernr eq '00000001'";
self.setBusy(true);
this.oModel.read(url, {
success: function(res) {
// ...
},
error: function() {
// ...
}
});
}
I don't know why the filter in url is not working now?
Check if your OData service supports the $filter query in the first place.
Use the read method correctly:myV2ODataModel.read("/PersonalDetailSet"/* No $filter queries here! */, {
filters: [ // <-- Should be an array, not a Filter instance!
new Filter({ // required from "sap/ui/model/Filter"
path: "myField",
operator: FilterOperator.EQ, // required from "sap/ui/model/FilterOperator"
value1: "..."
})
],
// ...
});
API reference: sap.ui.model.odata.v2.ODataModel#read
API reference: sap.ui.model.Filter
First you check whether you are getting model in the scope or not. As i can see this.oModel which is not proper way of getting model. Better use this.getModel() or this.getView().getModel() and then check the call. Passing filter is not the right way but still it should work.
If you want to apply additional URL Parameters in the read function you have to do this via the "urlParameters" parameter:
getGuid: function(pernr){
var self = this;
var url = "/PersonalDetailSet";
self.setBusy(true);
this.oModel.read(url, {
urlParameters: {
"$filter" : "Pernr eq '00000001'"
},
success: function(res){
self.setBusy(false);
self.guid = res.results[0].Guid;
},
error: function() {
self.setBusy(false);
}
});
}
I have this helper
myClub: function(){
var currentUserId = Meteor.userId();
var user = Meteor.users.findOne({_id: currentUserId});
return user;
}
I want it to return user.role
Here is my user in MongoDB
{
"_id" : "RdirmrLG3t8qBk4js",
"createdAt" : ISODate("2016-04-17T19:40:56.877Z"),
"services" : {
"password" : {
"bcrypt" : "$2a$10$cPe92XR9DT238bH/RanYEu.J6K2ImvAEbWOcVq6j9luI0BH08Qdly"
},
"resume" : {
"loginTokens" : [
{
"when" : ISODate("2016-04-17T19:51:49.474Z"),
"hashedToken" : "uVKUj/7JEkkOuizXhjl212Z38E47HXCex+D4zRikQ1k="
}
]
}
},
"username" : "worker",
"role" : "worker",
"club" : "hzSKAJfPXo7hSpTYS"
}
The code above works just fine. So it finds the current user and outputs info about it. But when I change user to user.role I get the following errormessage.
TypeError: Cannot read property 'role' of undefined
at Object.myClub
How can it be undefined? Is my syntax incorrect?
Template helpers are reactive, which means they update themselves as the app state changes or new data appears. In your case, the helper is called immediately when the template is rendered and before the Meteor.users collection is filled. Therefore, the .findOne() method returns undefined. It will be corrected in the second pass after new data arrives.
The simple fix here is to check whether the data is present inside the helper:
myClub: function(){
var currenUserId = Meteor.userId();
var user = Meteor.users.findOne({_id: currenUserId});
if(!user) return 'NO DATA';
return user.role;
},
In real life you'll probably want to wait for the basic data to be loaded before you render the template. That is usually done on the controller level.
Try:
myClub: function(){
return Meteor.user() && Meteor.user().role;
}
This is shorthand for return the role if there's a user.
As far as the role field not showing up, make sure that you are publishing that key from the server and subscribing to it. For example:
Meteor.publish('me',function(){
return Meteor.users.find(this.userId,{fields: {role: 1, username: 1, profile: 1, emails: 1}});
});
And on the client:
var me = Meteor.subscribe('me');
if ( me.ready() ) console.log("Ta-da! The role is: "+Meteor.user().role);
make sure that you subscribed to all data you need.
By the way, you can try following:
role: function(){ return (Meteor.user() || {}).role; }
Cheers
want to convert below line
rows.element(by.xpath(".//*[#ng-model='strategy.COMMENT']")).clear()
into page object like
rows.dataCatcherPage.strategyAUMValue.clear()
But i am getting the error
"Failed: Cannot read property 'strategyAUMValue' of undefined"
This is the Page object
strategyAUMValue: {
get: function () {
return element(by.xpath(".//*[#ng-model='strategy.AUM_VALUE']"));
}
},
How about this:
page
module.exports = new function () {
var elements : {
strategyAUMValue : element(by.xpath(".//*[#ng-model='strategy.AUM_VALUE']"))
};
this.clear = {
strategyAUMValue : elements.strategyAUMValue.clear()
};
this.getText = {
strategyAUMValue : elements.strategyAUMValue.getText()
};
};
spec
var dataCacherPage = require('./dataCacher.page.js');
describe('Data cacher', function(){
it('can clear the strategy aum value', function(){
dataCacherPage.clear.strategyAUMValue();
expect(dataCacherPage.clear.strategyAUMValue()).toEqual('', 'Strategy AUM Value should have been an empty string');
});
});
This lets your page elements be private(separating your framework layers), but gives you full access to all of the actions a test would be taking. You can expand on it by adding any other elements to the elements section, then adding to any this.clear/getText/isDisplayed type function that the element will need for testing.
Some extensibility:
module.exports = new function () {
var elements : {
strategyAUMValue : element(by.xpath(".//*[#ng-model='strategy.AUM_VALUE']")),
// Get an element where multiple exist
coolElement : $$('[name="coolElement"]')
};
this.clear = {
strategyAUMValue : elements.strategyAUMValue.clear()
};
this.getText = {
strategyAUMValue : elements.strategyAUMValue.getText(),
coolElement : elements.coolElement.getText()
};
};
.
var dataCacherPage = require('./dataCacher.page.js');
describe('Data cacher', function(){
it('can hit multiple elements', function(){
// Just add an index on coolElement to get whichever you want
expect(dataCacherPage.clear.coolElement(2)).toEqual('This is the third cool element on the page', 'Should have gotten the text from the third cool element');
});
});
i want to update a record:
www.mywebsite.com/REST/mytable/16
But; for mytable, i have to give two mandatory parameters:
www.mywebsite.com/REST/mytable?param1=this¶m2=that
And if i want to take the model from this collection using the following, the record can't be found:
www.mywebsite.com/REST/mytable?param1=this¶m2=that/16
This is realized by the following code:
var Model = Backbone.Model.extend({
idAttribute : "ID"
});
var Col = Backbone.Collection.extend({
model : Model,
url : $scope.base + $scope.selected.table.entity.Name + "?param1=1¶m2=2"
});
connector.fetch().then(function () {
var record = connector.get(toBeChangedRecordId);
record.set(props); //attributes as json
.save({
success : $scope.putCallback,
error : $scope.putCallback
});
}
It doesn't work because in the url above, no record is found. Instead of this, i need another way, so i can just give my ID to change the record (thus www.mywebsite.com/REST/mytable/16 + JSON object. How is that possible?
When you are doing a dynamic URL like this you can wrap the url method in a function like so
Backbone.Model.extend({
idAttribute : "ID",
url: function() {
var idStr = ''
if (this.isNew()) {
idStr = '/' + this.get('id')
}
return 'http://www.mywebsite.com/REST/mytable' + idStr + '?param1=' + this.get('param1') + '¶m2=' + this.get('param2');
}
});
Also, you declared your url was semantically declared wrong. You have the query string in the wrong place.