Related
I'm using the Grid component from Kendo UI on my Web API application. My records are being loaded correctly and even the delete is working, but unfortunately the Post and Update are not working. I got the error message on the response of the request: message: "An error has occurred.", exceptionMessage: "Value cannot be null. ↵Parameter name: entity",…}
Bellow part of my view and controller. What am I missing? Trying lots of things. *The field names are lower case because I'm using CamelCase.
$(document).ready(function () {
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "/api/products",
dataType: "json"
},
update: {
url: function (data) {
return "/api/products/" + data.id;
},
dataType: "json",
type: "PUT"
},
destroy: {
url: function (data) {
return "/api/products/" + data.id;
},
dataType: "json",
type: "DELETE"
},
create: {
url: "/api/products",
dataType: "json",
type: "POST"
},
parameterMap: function (options, operation) {
if (operation !== "read" && options.models) {
return { models: kendo.stringify(options.models) };
}
}
},
batch: false,
pageSize: 20,
schema: {
model: {
id: "id",
fields: {
id: { editable: false, nullable: true },
name: { validation: { required: true } },
description: { validation: { required: true } }
}
}
}
});
$("#grid").kendoGrid({
dataSource: dataSource,
pageable: true,
height: 550,
toolbar: ["create"],
columns: [
{ field: "name", title: "Name" },
{ field: "description", title: "Description" },
{ command: ["edit", "destroy"], title: " ", width: "250px"
}],
editable: "popup"
});
And this is part of my controller and repository:
public IHttpActionResult GetProducts()
{
var products = _productRepository.GetProducts();
return Ok(products);
}
[HttpPost]
public IHttpActionResult CreateProduct(Product product)
{
_productRepository.CreateProduct(product);
_productRepository.SaveProduct();
return Ok();
}
[HttpPut]
public IHttpActionResult UpdateProduct(int id, Product product)
{
var productInDb = _productRepository.GetProduct(id);
if (productInDb == null)
return NotFound();
_productRepository.UpdateProduct(product);
_productRepository.SaveProduct();
return Ok();
}
public Product GetProduct(int id)
{
return _context.Products.SingleOrDefault(p => p.Id == id);
}
public void CreateProduct(Product product)
{
_context.Products.Add(product);
}
public void UpdateProduct(Product product)
{
_context.Entry(product).State = EntityState.Modified;
}
public void SaveProduct()
{
_context.SaveChanges();
}
UPDATE
I think parameterMap function was wrong in the first place because when Posting or Updating it was never entering in the condition, so here it goes the parameterMap updated. The POST worked after that change (it's not just closing the window and repopulating the grid, I don't know why). But unfortunately the Update is still not working as I receive the following error inside controller "Attaching an entity of type 'Models.Product' failed because another entity of the same type already has the same primary key value. ". What am I missing in this situation?
parameterMap: function (options) {
return kendo.stringify(options);
},
type: "json"
I managed to solve it with the help in the comments (basically the main problem was the parameterMap, and then a fill tweeks were needed as well as passing back the entity in the return of the controller methods). I'm putting the updated code below (only the part that was changed).
View:
$(document).ready(function () {
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "/api/products",
dataType: "json"
},
update: {
url: function (data) {
return "/api/products/" + data.id;
},
dataType: "json",
type: "PUT"
},
destroy: {
url: function (data) {
return "/api/products/" + data.id;
},
dataType: "json",
type: "DELETE"
},
create: {
url: "/api/products",
dataType: "json",
type: "POST"
},
parameterMap: function (options) {
return kendo.stringify(options);
},
type: "json"
},
batch: false,
pageSize: 20,
schema: {
model: {
id: "id",
fields: {
id: { editable: false, nullable: true },
name: { validation: { required: true } },
description: { validation: { required: true } }
}
}
}
});
$("#grid").kendoGrid({
dataSource: dataSource,
pageable: true,
height: 550,
toolbar: ["create"],
columns: [
{ field: "name", title: "Name" },
{ field: "description", title: "Description" },
{ command: ["edit", "destroy"], title: " ", width: "250px"
}],
editable: "popup"
});
Controller:
public IHttpActionResult GetProducts()
{
var products = _productRepository.GetProducts();
return Ok(products);
}
[HttpPost]
public IHttpActionResult CreateProduct(Product product)
{
_productRepository.CreateProduct(product);
_productRepository.SaveProduct();
return Ok(product);
}
[HttpPut]
public IHttpActionResult UpdateProduct(int id, Product product)
{
_productRepository.UpdateProduct(product);
_productRepository.SaveProduct();
return Ok(product);
}
Here is my method:
removeRole: function(role) {
check(role, String);
var user = Meteor.user();
if (!user || ! AccountsAdmin.checkForAdminAuthentication(user))
throw new Meteor.Error(401, "You need to be an authenticated admin");
// handle non-existing role
if (Meteor.roles.find({name: role}).count() < 1 )
throw new Meteor.Error(422, 'Role ' + role + ' does not exist.');
if (role === 'admin')
throw new Meteor.Error(422, 'Cannot delete role admin');
// remove the role from all users who currently have the role
// if successfull remove the role
Meteor.users.update(
{roles: role },
{$pull: {roles: role }},
{multi: true},
function(error) {
if (error) {
throw new Meteor.Error(422, error);
} else {
Roles.deleteRole(role);
}
}
);
},
Here is the error I receive when looking at the call in Kadira:
message: After filtering out keys not in the schema, your modifier is now empty
stack:
Error: After filtering out keys not in the schema, your modifier is now empty
at [object Object].doValidate (packages/aldeed_collection2-core/lib/collection2.js:282:1)
at [object Object]._.each.Mongo.Collection.(anonymous function) [as update] (packages/aldeed_collection2-core/lib/collection2.js:83:1)
at [object Object].Meteor.methods.removeRole (packages/accounts-admin-ui-bootstrap-3/server/methods.js:86:1)
Line 86 of that methods.js is "Meteor.users.update" in the code above. When trying to debug this using breakpoints it appears this is where the error is happening as well.
I am using this package to help with the user management UI that I am creating, although I have did some customizing to it. I have also tested this on a different version of my project for troubleshooting and I have found that it works when I don't use the Collection2 package.
Here is my custom schema setup:
Schema = {};
Schema.UserProfile = new SimpleSchema({
userProfile: {
type: Object
},
'userProfile.firstName': {
type: String,
optional: true,
label: "First Name"
},
'userProfile.lastName': {
type: String,
optional: true,
label: "Last Name"
},
'userProfile.birthday': {
type: Date,
optional: true,
label: "Date of Birth"
},
'userProfile.contactEmail': {
type: String,
optional: true,
label: "Email"
},
'userProfile.gender': {
type: String,
allowedValues: ['Male', 'Female'],
optional: true,
label: "Gender"
},
'userProfile.address': {
type: String,
optional: true,
label: "Address"
},
'userProfile.city': {
type: String,
optional: true,
label: "City"
},
'userProfile.stateProvince': {
type: String,
optional: true,
label: "State/Province"
},
'userProfile.postalCode': {
type: String,
optional: true,
label: "Postal Code"
},
'userProfile.phoneNumber': {
type: String,
optional: true,
label: "Phone Number"
},
userProfilePayment: {
type: Object
},
'userProfilePayment.paymentEmail': {
type: String,
optional: true,
label: "Payment Email"
},
'userProfilePayment.address': {
type: String,
optional: true,
label: "Address"
},
'userProfilePayment.city': {
type: String,
optional: true,
label: "City"
},
'userProfilePayment.stateProvince': {
type: String,
optional: true,
label: "State/Province"
},
'userProfilePayment.postalCode': {
type: String,
optional: true,
label: "Postal Code"
},
'userProfilePayment.phoneNumber': {
type: String,
optional: true,
label: "Phone Number"
},
});
Schema.User = new SimpleSchema({
username: {
type: String,
// For accounts-password, either emails or username is required, but not both. It is OK to make this
// optional here because the accounts-password package does its own validation.
// Third-party login packages may not require either. Adjust this schema as necessary for your usage.
optional: true
},
emails: {
type: Array,
// For accounts-password, either emails or username is required, but not both. It is OK to make this
// optional here because the accounts-password package does its own validation.
// Third-party login packages may not require either. Adjust this schema as necessary for your usage.
optional: true
},
"emails.$": {
type: Object
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email
},
"emails.$.verified": {
type: Boolean
},
createdAt: {
type: Date
},
profile: {
type: Schema.UserProfile,
optional: true
},
// Make sure this services field is in your schema if you're using any of the accounts packages
services: {
type: Object,
optional: true,
blackbox: true
},
// Add `roles` to your schema if you use the meteor-roles package.
// Option 1: Object type
// If you specify that type as Object, you must also specify the
// `Roles.GLOBAL_GROUP` group whenever you add a user to a role.
// Example:
// Roles.addUsersToRoles(userId, ["admin"], Roles.GLOBAL_GROUP);
// You can't mix and match adding with and without a group since
// you will fail validation in some cases.
roles: {
type: Object,
optional: true,
blackbox: true
},
// In order to avoid an 'Exception in setInterval callback' from Meteor
heartbeat: {
type: Date,
optional: true
},
// Added to work with mizzao:user-status
status: {
type: Object,
optional: true,
blackbox: true
}
});
Meteor.users.attachSchema(Schema.User);
Meteor.users.allow({
// NOTE: The client should not be allowed to add users directly!
insert: function(userId, doc) {
// only allow posting if you are logged in
console.log("doc: " + doc + " userId: " + userId);
return !! userId;
},
update: function(userId, doc, fieldNames) {
// only allow updating if you are logged in
console.log("doc: " + doc + " userId: " + userId);
// NOTE: a user can only update his own user doc and only the 'userProfile' and 'userProfilePayment' field
return !! userId && userId === doc._id && _.isEmpty(_.difference(fieldNames, ['userProfile, userProfilePayment']));
},
/* NOTE: The client should not generally be able to remove users
remove: function(userID, doc) {
//only allow deleting if you are owner
return doc.submittedById === Meteor.userId();
}
*/
});
To remove a key in a mongodb update you want to use the $unset operator:
Meteor.users.update({ roles: role },{ $unset: { roles: 1 }}, { multi: true })
It's just a bit unusual that in your model a user can only have a single role.
I have an app in which I'm using a template helper. I have the following code:
UI.registerHelper('ProfileNameByUserId', function(userid) {
console.log('Userid: ' + userid);
var user = Meteor.users.findOne({'_id': userid});
console.log.log('User:' + user);
return user.username
});
I'm calling this in my template as follows:
{{#each getDocuments}}
{{ProfileNameByUserId userid}}
{{/each}}
and in the template helper:
Template.documentsIndex.helpers({
getDocuments: function () {
return Documents.find({}, { sort: { createdAt: -1 }});
}
});
The publish and subscribe are as follows:
Routes.route('/documents', {
name: 'documents',
subscriptions: function (params, queryParams) {
this.register('documentsIndex', Meteor.subscribe('documents'));
},
action: function (params, queryParams) {
.....
});
}
});
Meteor.publish('documents', function () {
return Documents.find({})
});
I'm sure the userId is passed on, as a console.log statement shows the correct id. The issue is that the user is 'undefined' so it can't find the username.
I'm using SimpleSchema to define a users schema which looks as follows:
Users = Meteor.users;
Schema = {};
Schema.UserProfile = new SimpleSchema({
firstName: {
type: String,
optional: true
},
lastName: {
type: String,
optional: true
},
gender: {
type: String,
allowedValues: ['Male', 'Female'],
optional: true
},
});
Schema.User = new SimpleSchema({
username: {
type: String,
optional: true
},
emails: {
type: Array,
optional: true
},
"emails.$": {
type: Object
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email
},
"emails.$.verified": {
type: Boolean
},
createdAt: {
type: Date,
optional: true,
denyUpdate: true,
autoValue: function() {
if (this.isInsert) {
return new Date();
}
}
},
profile: {
type: Schema.UserProfile,
optional: true
},
services: {
type: Object,
optional: true,
blackbox: true
},
roles: {
type: [String],
optional: true
}
});
Meteor.users.attachSchema(Schema.User);
});
Replacing Meteor.users.findOne() in the template helper with Users.findOne() does not work either.
Any idea why user remains undefined?
You need to add a publication and subscription for the users that you want to show.
In the most general case in which all users are published:
Meteor.publish('allUsers', function () {
return Meteor.users.find();
});
Subscribe to this in your route and you will not have the user undefined in your helper.
Note that you should only publish the users that you need, but since I do not know you application structure I cannot give you a query for that.
I am newbie in stackoverflow and newbie with Kendo UI and newbie with web development ... I was born yesterday :). Joking apart my question is not really a question, I know the forum rules over specific questions but I need help.
My problem is this:
I adapted the Kendo UI MVC Music Store tutorial but with use MVC ASP.net (I work with Delphi) and it not works.
I have two files:
Category.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Administración de Categorías</title>
<link href="kendo/styles/kendo.common.min.css" rel="stylesheet" type="text/css" />
<link href="kendo/styles/kendo.default.min.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="css/menuvir.css" type="text/css"/>
<script src="kendo/js/jquery.min.js" type="text/javascript"></script>
<script src="kendo/js/kendo.web.min.js" type="text/javascript"></script>
</head>
<body>
<div id="categGrid"></div>
<script src="js/category.js type="text/javascript"></script>
</body>
</html>
and Category.js
(function (window, $, kendo) {
var getCategAsync = function () {
var deferred = $.Deferred(),
translateCateg = function (data) {
deferred.resolve($.map(data.result, function(item) {
return {
value: item.ID,
text: item.Description
};
}));
},
loadCateg = function () {
new kendo.data.DataSource({
type: "json",
transport: {
read: "/w/Category?select=ID,Description"
},
schema: {
data: 'result'/*,
total: store.config.wcfSchemaTotal*/
}
}).fetch(function (data) {
translateCateg(data);
});
};
window.setTimeout(loadCateg, 1);
return deferred.promise();
};
var getLangAsync = function () {
var deferred = $.Deferred(),
translateLang = function (data) {
deferred.resolve($.map(data.result, function(item) {
return {
value: item.ID,
text: item.Description
};
}));
},
loadLang = function () {
new kendo.data.DataSource({
type: "json",
transport: {
read: "/w/Language?select=ID,Description"
},
schema: {
data: 'result'/*,
total: store.config.wcfSchemaTotal*/
}
}).fetch(function (data) {
translateLang(data);
});
};
window.setTimeout(loadLang, 1);
return deferred.promise();
};
var initGrid = function (categs, langs, categEditor, langEditor) {
$("#categGrid").kendoGrid({
sortable: true,
groupable: false, //true,
filterable: false, //true,
pageable: true,
editable: "inline",
toolbar: ["create"],
dataSource: {
type: "json",
pageSize: 10,
serverPaging: false, //true,
serverFiltering: false, //true,
serverSorting: false, //true,
sort: { field: "SortOrder", dir: "asc" },
transport: {
type: "json",
read: {
url: "/w/Category?select=ID,Description",
type: "GET"
}/*,
update: {
url: function (data) {
return store.config.albumsUrl + "(" + data.AlbumId + ")"
},
type: "PUT"
},
destroy: {
url: function (data) {
return store.config.albumsUrl + "(" + data.AlbumId + ")";
},
type: "DELETE"
},
create: {
url: store.config.albumsUrl,
type: "POST"
} */
},
schema: {
data: "result",
//total: store.config.wcfSchemaTotal,
model: {
id: "ID",
fields: {
ID: { type: "number" },
Description: { type: "string", validation: {required: true} },
Language: { type: "number", defaultValue: 1 },
SortOrder: { type: "number", defaultValue: 0 },
Status: { type: "number", defaultValue: 0 },
Parent: { type: "number", defaultValue: 0 }
}
}
},
},
columns: [
{ field: "ID", title: "ID", editable: false, filterable: false, width: 20 },
{ field: "Description", title: "Descripción", filterable: false, width: 150 },
{ field: "Language", title: "Idioma", values: langs, editor: langEditor, filterable: false, width: 50 },
{ field: "SortOrder", title: "Orden", filterable: false, width: 20 },
{ field: "Status", title: "Estado", filterable: false, width: 50 },
{ field: "Parent", title: "Subcategoría de", values: categs, editor: categEditor, filterable: false, width: 150 },
{ command: ["edit", "destroy"], title: " ", width: "160px" }
]
});
};
// Wait for both the genres and artists lists to load.
$.when(getCategAsync(), getLangAsync())
.done(function(categs, langs) {
var categEditor = function (container, options) {
$('<input data-text-field="text" data-value-field="value" data-bind="value:' + options.field + '" />')
.appendTo(container)
.kendoComboBox({
autoBind: false,
dataSource: categs
});
};
var langEditor = function (container, options) {
$('<input data-text-field="text" data-value-field="value" data-bind="value:' + options.field + '" />')
.appendTo(container)
.kendoComboBox({
autoBind: false,
dataSource: langs
});
};
initGrid(categs, langs, categEditor, langEditor);
});
})(window, jQuery, kendo);
When I execute this nothing is showing and no error in Firebug console.
What's wrong ? Any help is appreciatted.
Thanks in advance and sorry for my english.
UPDATE
Sorry, I forgot update the Category.html code here, but I always had the value right "id" and yet it not works. Thanks for the quick response.
Well, for starters your JQuery is attempting to create a KendoGrid on an ID that isn't present in your HTML
$("#categGrid").kendoGrid(
doesn't match anything in your HTML. Did you mean
$("#grid").kendoGrid({
which would find
<div id="grid"></div>
I solved the problem. I changed some options I adapted erroneously.
This is the code that works.
(function (window, $, kendo) {
var getCategAsync = function () {
var deferred = $.Deferred(),
translateCateg = function (data) {
deferred.resolve($.map(data.items, function(item) {
return {
value: item.ID,
text: item.Description
};
}));
},
loadCateg = function () {
new kendo.data.DataSource({
transport: {
read: {
url: "/w/Category?select=ID,Description",
dataType: "json",
type: "GET"
}
},
schema: {
data: 'result'/*,
total: store.config.wcfSchemaTotal*/
}
}).fetch(function (data) {
translateCateg(data);
});
};
window.setTimeout(loadCateg, 1);
return deferred.promise();
};
var getLangAsync = function () {
var deferred = $.Deferred(),
translateLang = function (data) {
deferred.resolve($.map(data.items, function(item) {
return {
value: item.ID,
text: item.Description
};
}));
},
loadLang = function () {
new kendo.data.DataSource({
transport: {
read: {
url: "/w/Language?select=ID,Description",
dataType: "json",
type: "GET"
}
},
schema: {
data: 'result'/*,
total: store.config.wcfSchemaTotal*/
}
}).fetch(function (data) {
translateLang(data);
});
};
window.setTimeout(loadLang, 1);
return deferred.promise();
};
var initGrid = function (categs, langs, categEditor, langEditor) {
$("#categGrid").kendoGrid({
sortable: true,
groupable: false, //true,
filterable: false, //true,
pageable: true,
editable: "inline",
toolbar: ["create"],
dataSource: {
type: "json",
pageSize: 10,
serverPaging: false, //true,
serverFiltering: false, //true,
serverSorting: false, //true,
sort: { field: "SortOrder", dir: "asc" },
transport: {
read: {
url: "/w/Category?select=*",
type: "GET",
dataType: "json"
}/*,
update: {
url: function(data) {
return "/w/Category?ID=" + data.ID;
},
contentType: "application/json",
type: "PUT"
},
destroy: {
url: function (data) {
return store.config.albumsUrl + "(" + data.AlbumId + ")";
},
type: "DELETE"
},
create: {
url: store.config.albumsUrl,
type: "POST"
} */
},
schema: {
data: "result",
total: function(response) {
return response.result.length;
},
model: {
id: "ID",
fields: {
ID: { type: "number" },
Description: { type: "string", validation: {required: true} },
Language: { type: "number", defaultValue: 1 },
SortOrder: { type: "number", defaultValue: 0 },
Status: { type: "number", defaultValue: 0 },
Parent: { type: "number", defaultValue: 0 }
}
}
},
},
columns: [
{ field: "ID", title: "ID", editable: false, filterable: false, width: 20 },
{ field: "Description", title: "Descripción", filterable: false, width: 150 },
{ field: "Language", title: "Idioma", values: langs, editor: langEditor, filterable: false, width: 50 },
{ field: "SortOrder", title: "Orden", filterable: false, width: 20 },
{ field: "Status", title: "Estado", filterable: false, width: 50 },
{ field: "Parent", title: "Subcategoría de", values: categs, editor: categEditor, filterable: false, width: 150 },
{ command: ["edit", "destroy"], title: " ", width: "160px" }
]
});
};
// Wait for both the genres and artists lists to load.
$.when(getCategAsync(), getLangAsync())
.done(function(categs, langs) {
var categEditor = function (container, options) {
$('<input data-text-field="text" data-value-field="value" data-bind="value:' + options.field + '" />')
.appendTo(container)
.kendoComboBox({
autoBind: false,
dataSource: categs
});
};
var langEditor = function (container, options) {
$('<input data-text-field="text" data-value-field="value" data-bind="value:' + options.field + '" />')
.appendTo(container)
.kendoComboBox({
autoBind: false,
dataSource: langs
});
};
initGrid(categs, langs, categEditor, langEditor);
});
})(window, jQuery, kendo);
Thanks.
Greeting,
I'm using jquery Plugins/Validation library. I want to allow validation on submitting but I'm not sure where I should insert the code:
I know that I can user submitHandler for that but after reading the document I had hard time to implement it so I need your help guys.
jquery validation is working ok but the problem that the form still submitted even there are invalid inputs.
here is my validation function and I want to know how can I make it to not submit the form if there is invalid input.
by the way, I'm using asp.net button for submitting the form.
here is my code:
$(document).ready(function() {
$("#aspnetForm").validate({
rules: {
"<%=txtHomePhone.UniqueID %>": {
phonehome: true
},
"<%=txtMobileHome.UniqueID %>": {
mobilephone: true
},
"<%=txtFaxHome.UniqueID %>": {
faxhome: true
},
"<%=txtEmailHome.UniqueID %>": {
email: true
},
"<%=txtZipCodeHome.UniqueID %>": {
ziphome: true
},
//work
"<%=txtPhonework.UniqueID %>": {
phonework: true
},
"<%=txtMobileWork.UniqueID %>": {
mobilework: true
},
"<%=txtFaxWork.UniqueID %>": {
faxwork: true
},
"<%=txtEmailWork.UniqueID %>": {
email: true
},
"<%=txtWebSite.UniqueID %>": {
url: true
},
"<%=txtZipWork.UniqueID %>": {
zipwork: true
}
},
errorElement: "mydiv",
wrapper: "mydiv", // a wrapper around the error message
errorPlacement: function(error, element) {
offset = element.offset();
error.insertBefore(element)
error.addClass('message'); // add a class to the wrapper
error.css('position', 'absolute');
error.css('left', offset.left + element.outerWidth());
error.css('top', offset.top - (element.height() / 2));
}
});
to enable debugon submit I need to set debug to true in validate function for the rules by adding this line : debug: true,
correct code:
$(document).ready(function() {
$("#aspnetForm").validate({
debug: true,
rules: {
"<%=txtHomePhone.UniqueID %>": {
phonehome: true
},
"<%=txtMobileHome.UniqueID %>": {
mobilephone: true
},
"<%=txtFaxHome.UniqueID %>": {
faxhome: true
},
"<%=txtEmailHome.UniqueID %>": {
email: true
},
"<%=txtZipCodeHome.UniqueID %>": {
ziphome: true
},
//work
"<%=txtPhonework.UniqueID %>": {
phonework: true
},
"<%=txtMobileWork.UniqueID %>": {
mobilework: true
},
"<%=txtFaxWork.UniqueID %>": {
faxwork: true
},
"<%=txtEmailWork.UniqueID %>": {
email: true
},
"<%=txtWebSite.UniqueID %>": {
url: true
},
"<%=txtZipWork.UniqueID %>": {
zipwork: true
}
},
errorElement: "mydiv",
wrapper: "mydiv", // a wrapper around the error message
errorPlacement: function(error, element) {
offset = element.offset();
error.insertBefore(element)
error.addClass('message'); // add a class to the wrapper
error.css('position', 'absolute');
error.css('left', offset.left + element.outerWidth());
error.css('top', offset.top - (element.height() / 2));
}
});