I am using angularjs-rails-resource , in my Rails Angular App.
Account Resources
myApp.factory('Account', ['railsResourceFactory','railsSerializer', function
(railsResourceFactory,railsSerializer) {
return railsResourceFactory({
url: '/accounts',
name: 'account',
serializer: railsSerializer(function () {
this.nestedAttribute('address');
})
});
}]);
UserController.js
function userController($scope,$location,Auth,$rootScope,$http,Useraccount,Account) {
$scope.profileUpdate = function() {
//Useraccount.save(); // THIS WORKS
$scope.account = {}
$scope.account.save() // Throwing error : undefined function save
}
}
UserAccount Service
myApp.service('Useraccount',function(Auth,$location,$rootScope,Account){
var account;
var query = function(){
var promise = Account.query().then(function (results) {
account = results;
}, function (error) {
alert("Went Wrong while fetching User Account!!")
});
return promise;
}
var save = function() {
account.save().then(function (results) {
console.log(results);
}, function (error) {
alert("Went Wrong!!")
});
}
return {
query:query,
save:save
}
})
});
I am not sure why the save function from UserController is not working though I have imported Account resources as dependency. I did same in service , but it was working there. Any clue will be helpful.
You are actually calling the save() method for an empty javascript object. I don't see the point here.
Anyway you need an Angular object to do so. So either load account data from server.
$scope.accounts = Account.query(); // Will be an Array of accounts
Or create new instance of Account
$scope.account = new Account(); // An empty object
Related
In my app the User authenticates then takes a quiz. I want to save the quiz results to the User schema. When I run the following, the correct information prints to the console but saving gives me the error:
//Error printing to console:
User.save(function(err){ ^
TypeError: Object function model(doc, fields, skipId) {
if (!(this instanceof model))
return new model(doc, fields, skipId);
Model.call(this, doc, fields, skipId);
} has no method 'save'
//update the user with the kitten Type
app.post('/api/kittens', isLoggedIn, function (req, res, done) {
console.log(req.user.kittenType); //an empty set by default
console.log(req.body.kittenType); //the quiz result
User.findOne({ 'kittenType': req.user.kittenType}, function(err, user) {
if(err)
return done(err);
if(user) {
User.kittenType = req.body.kittenType;
User.save(function(err){
if(!err){
console.log('yay');
}
else {
console.log(err);
}
});
console.log(User.kittenType);
}
});
});
var userSchema = mongoose.Schema({
user : {
type: mongoose.Schema.ObjectId,
ref: 'User'
},
kittenType : String,
local : {
email : String,
password : String,
petname : String,
path : String,
},
});
The problem was capitalization:
should be "user.kittenType" and "user.save" not "User.save"
i am working with the new VS2013 and created OData Controller with 2 models , Store and Products as client i have used KO,BreezeJS and DataJs
i saw that expand is not working, i have send this issue to microsoft poeple in codeplex site and they told me that all is ok with my code
my.vm = {
stores: ko.observableArray([]),
load: function () {
var serverAddress = "/odata";
breeze.config.initializeAdapterInstances({ dataService: "OData" });
var manager = new breeze.EntityManager(serverAddress);
var query = breeze.EntityQuery.from("Store").expand("Products");
manager.executeQuery(query, function (data) {
var results = data.results;
$.each(data.results, function (i, c) {
my.vm.stores.push(c);
});
});
}
};
adding the request/response
http://localhost:16894/odata/Store?$expand=Products
{
"odata.metadata":"/odata/$metadata#Store","value":[
{
"odata.type":"WebApplication1.Models.Store","odata.id":"/odata/Store(1)","Products#odata.navigationLinkUrl":"/odata/Store(1)/Products","Products":[
{
"odata.type":"WebApplication1.Models.Product","odata.id":/odata/Product(1)","ID":1,"Name":"1"
},{
"odata.type":"WebApplication1.Models.Product","odata.id":"/odata/Product(2)","ID":2,"Name":"2"
}
],"ID":1,"Name":"1"
},{
"odata.type":"WebApplication1.Models.Store","odata.id":/odata/Store(2)","Products#odata.navigationLinkUrl":"/odata/Store(2)/Products","Products":[
{
"odata.type":"WebApplication1.Models.Product","odata.id":"/odata/Product(2)","ID":2,"Name":"1"
},{
"odata.type":"WebApplication1.Models.Product","odata.id":"/odata/Product(3)","ID":3,"Name":"2"
}
],"ID":2,"Name":"1"
}
]
}
I am trying to create a modal that will tell the user their submission was successfully submitted. This works fairly well, but the only problem is I have to declare each of my properties and assign it a value, then in the Json method I have accept all those parameters then do something with them. Is there any way to do this with a ViewModel? Or any otherway that this can be done using a ViewModel?
controller:
public Json Send(string var1, string var2)
{
...
if(valid)
return new Json(true, JsonRequestBehavior.AllowGet);
else
return new Json(false, JsonRequestBehavior.AllowGet);
}
javascript:
function submitData() {
$.ajax({
url: "/Report/Send",
type: "POST",
dataType: "json",
data: { var1 = Model.var1, var2 = Model.var2... },
success: function (data) {
if(data) {
showDialog();
}
else {
$("#errorDiv").load('Report/Error/');
}
},
error: function (somefunction) { }
});
}
Yes, create a ViewModel POCO class:
var myJsonResult = new { result: true };
return Json(myJsonResult);
You can also use a strongly typed ViewModel and return that:
var myJsonResult = new CustomResult { result: true };
return Json(myJsonResult);
Then just check that property on the class in your success function:
success: function (data) {
if(data.result) {
showDialog();
}
else if(!data.result) {
$("#errorDiv").load('Report/Error/');
}
},
EDIT:
You might also want to look at jquery's .serialize() method:
data: $("#myForm").serialize()
This will be useful if you bind your ViewModel to form elements and need to post them back to the server.
Everything seems correct in my $.ajax call within the .bind on create.jstree. However, the call to the controller (I'm using MVC 3) is not occurring for some reason. I put a breakpoint on the POST function that's referenced by the ajax call, but it never even gets called. Which leads me to believe that there's something wrong with the combination of the bind and ajax call that is preventing the post function from ever being called. I would appreciate the advice.
jstree code:
$("#RequirementsTree")
.bind("select_node.jstree", function(event, data) {
if(is_requirement_node(data))
{
var id = data.rslt.obj.attr("id");
if(id != null)
{
$("#RequirementsTree").jstree('close_all')
}
else {
alert("Requirement node select error");
}
}
})
.bind("create.jstree", function(e, data) {
alert(data.rslt.obj.text());
alert(ParentNode);
// Ajax call to Server with parent node id and new node text
debugger;
$.ajax({
type: "POST",
url: function(node) {
return "/RMS/insertRequirementNode";
},
data: {
ParentID : ParentNode,
ChildNodeText : data.rslt.obj.text()
},
success: function(new_data) {
return new_data;
}
});
ParentNode = null;
if (data.rslt.parent == -1) {
alert("Can not create new root directory");
// Rollback/delete the newly created node
$.jstree.rollback(data.rlbk);
return;
}
BranchReqFLag = null;
}).jstree({
json_data: {
data: RBSTreeModel,
ajax: {
type: "POST",
data: function (n) {
return {
NodeID: n.attr("id").substring(4),
Level: n.attr("name").substring(7)
};
},
url: function (node) {
return "/Audit/GetRequirementsTreeStructure";
},
success: function (new_data) {
return new_data;
}
}
},
contextmenu: {
items: function($node) {
return {
createItem : {
"label" : "Create New Branch",
"action" : function(obj) { this.create(obj); BranchReqFlag = "Branch"; ParentNode = obj.attr("id").substring(4);}
},
renameItem : {
"label" : "Rename Branch",
"action" : function(obj) { this.rename(obj);}
}
};
}
},
plugins: ["themes", "json_data", "ui", "crrm", "contextmenu"]
});
Controller POST function:
[AllowAnonymous]
[HttpPost]
public int insertRequirementNode(int ParentID, string ChildNodeText)
{
RBSText CurrNode = new RBSText();
int CurrentNodeID = -1;
//CurrNode.RMSHierarchyText = ChildNodeText;
using (Contract ActiveContract = getContract())
{
try
{
// Inserts the new node beneath the Parent Node
CurrentNodeID = ActiveContract.CreateRMSNode(CurrNode, ActiveContract.ContractId, ActiveContract.user_id, 2, "Child");
}
catch (Exception ex)
{
throw ex;
}
}
return CurrentNodeID;
}
The URL specified in your $.ajax() function is likely wrong. Use #Url.Content() along with the the Server Root Wildcard: ~ to prefix your URL , so your URL always refers to the correct server root path no matter how your application is deployed, this assuming that you are setting up your jstree in a Razor View so you have access to the Razor Engine:
$.ajax({
type: "POST",
url: "#Url.Content("~/RMS/insertRequirementNode")",
data: {
ParentID : ParentNode,
ChildNodeText : data.rslt.obj.text()
},
success: function(new_data) {
return new_data;
}
});
If you are setting up jstree in a .js file, then you need to store the server root in a javascript variable defined in a Razor View first and refer to that variable instead.
I started using knockout.js and i really like it.
I use ASP.Net mvc , jQuery and knockout.js
My question is this:
lets say i have a management screen of a user, the user is my view model
inside the user i want an array of permissions
my user viewModel:
var userViewModelClass = function () {
var self = this;
ko.mapping.fromJS({
ID: "",
permissions: []
}, {}, self);
}
now.. if i do an ajax request to the server and get a JSON back i user the mapping plugin, and everything goes as expected
but... now i want my rendered permissions list to have an action like delete.
so i will need a permission object and then the array of permissions will be an array of permission objects. but how do i do that? how will the mapping plugin know that the object returned to him from the server in an array is actually on object like this one:
function permission() {
var self = this;
this.delete = function () {
};
ko.mapping.fromJS({
name: "",
level: ""
}, {}, self);
}
that's my first part of the question.
the second part:
lets say i got the model with an array of all permissions and they are all of this permission object. now i want each delete button in my view to be bind the the delete function inside the permission object.
using:
data-bind="click: delete"
what is the best implementation for a delete function? i thought about something like: makeing an ajax call to the server which will actually delete the permission from the user. then if the call succeeds remove the current permission from the observable array, then the view will update...
is that a good practice?
thanks!
First part. You need to use mapping options. In your userViewModelClass do this.
var userViewModelClass = function () {
var self = this;
ko.mapping.fromJS({
ID: "",
permissions: []
}, {
permissions: {
create: function(options) {
return new permission(options.data);
}
}
}, self);
}
And modify your permission object like so
function permission(config) {
var self = this;
this.delete = function () {
};
ko.mapping.fromJS($.extend({
name: "",
level: ""
}, config), {}, self);
}
Note I added the extend in so that your default structure will remain and be overwritten by incoming data.
Second part of your question. One possible way would be to pass a reference to the parent in your constructor. So the above mapping options would become
permissions: {
create: function(options) {
return new permission(options.data, self);
}
}
Then your delete could be something like.
this.delete = function () {
$.ajax(deleteurl, yourdata, function(result) {
// success
parent.permissions.remove(self);
}, function() {
// failure
display error message
}
};
EDIT
Alternate way as discussed in comments.
var userViewModelClass = function () {
var self = this;
ko.mapping.fromJS({
ID: "",
permissions: []
}, {
permissions: {
create: function(options) {
return new permission(options.data);
}
}
}, self);
this.delete = function(permission) {
self.permissions.remove(permission);
};
}
data-bind="click: $parent.delete"
Hope this helps.