Knockout Validation Only If a specific button is pressed - asp.net-mvc-3

https://github.com/ericmbarnard/Knockout-Validation/wiki/Native-Rules
I am using the knockout validation on my MCV3 page. The situation I have is that I have two buttons. one is Add To Collection, and other is Save. The Add to collection looks for following properties as they are required:
FirstName: ko.observable().extend({ required: true }),
LastName: ko.observable().extend({ required: true }),
Title: ko.observable(),
Email: ko.observable().extend({ required: true, email: true }),
Date1: ko.observable(new Date()).extend({ required: true }),
I have two functions defined that check if the page is valid:
first:
AddToCollection: function () {
if (!viewModel.isValid()) {
viewModel.errors.showAllMessages();
return false;
} else {
this.Collection.push(new Item(this.FirstName(), this.LastName(), this.Title(), this.Email()));
viewModel.clear();
}
},
and second:
save: function () {
if (!viewModel.isValid()) {
viewModel.errors.showAllMessages();
return false;
} else {
$.ajax({
url: '#Url.Action("DoSomethinn")',
type: "POST",
data: ko.toJSON(this),
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (result) {
}
});
}
}
The thing that I am trying to do is that I don't want the FirstName, LastName, and Email to be required if Save is called, only Date1 is validated, but FirstName, LastName, and Email is required when AddToCollectoin is called, but Date1 is not. How do set up the Only If Native Rule, or is there a better way of doing this.
Any help is much appreciated!

The onlyIf option could work here:
FirstName: ko.observable().extend({
required: {
params: true,
onlyIf: function(){ return someFlagIsTrue; }
}
You would need to set the someFlagIsTrue from your click event or other means.

Related

Passing parameter to MVC Action via Ajax always null

I looked at related questions to to form my ajax request but I can't figure out why this isn't working as the param is always null in the acion
I've done a console.log to check that item in 'data: { data: item }' has a value
//action
public async Task<IActionResult> DeleteMedia(string data)
{
$("#mediaTable").on('click', 'td:nth-child(7)', function () {
var item = $(this).parent().attr("id");
$("#MediaToDownload").val(item);
$.ajax({
url: '#Url.Action("DeleteMedia", "Home")',
type: 'get',
cache: false,
processData: false,
contentType: false,
data: { data: item },
success: function (data) {
location.href = data;
}
});
});
You need to send just the string, as JSON:
data: JSON.stringify(item)

How can I cause adding an invalid item to an observableArray to invalidate the validatedObservable with Knockout-Validation

I have a form with some fields and a list of items which a user can add to. For the form to be valid, all of the fields on the form and in all items of the list must be valid. When a new item is added to the list it will be invalid because all of the required fields will be blank.
Unfortunately, knockout-validation doesn't seem to see this and reports the form as valid. The individual fields in the list items will validate independently and show the "This field is required." message but the validatedObservable which contains everything reports isValid() as true. Even stranger, if I cause the form to become invalid by editing one of the fields that existed before the list addition, suddenly everything starts to work properly.
Here's an example of the issue I'm working with: http://jsfiddle.net/97Lr15zq/5/
ko.validation.init({
registerExtenders: true,
messagesOnModified: true,
insertMessages: true,
parseInputAttributes: true,
messageTemplate: null,
grouping: {
deep: true,
live: true
}
},
true);
var viewModel = {
items: ko.observableArray([]),
test: ko.observable('e').extend({ required: true }),
add: function(){
viewModel.items.push({
firstName: ko.observable('').extend({ required: true }),
lastName: ko.observable('').extend({ required: true })
});
},
submit: function() {
if (viewModel.errors.isValid()) {
alert('Thank you.');
}
else {
alert('Please check your submission. Errors: ' + viewModel.errors.errors().length);
viewModel.errors.errors.showAllMessages();
}
}
};
viewModel.errors = ko.validatedObservable({items: viewModel.items, test: viewModel.test});
ko.applyBindings(viewModel);
How can I get knockout-validation to start monitoring the new list items as soon as they're added?
This isn't ideal and I'm still hoping to find a cleaner solution but for now what I ended up doing is adding an observable to the viewModel and the validatedObservable who's only purpose is to be invalidated so that knockout-validate will start picking up the changes in the new list item.
http://jsfiddle.net/97Lr15zq/6/
var viewModel = {
items: ko.observableArray([]),
test: ko.observable('e').extend({ required: true }),
invalidator: ko.observable('a').extend({ required: true }),
add: function(){
viewModel.items.push({
firstName: ko.observable('').extend({ required: true }),
lastName: ko.observable('').extend({ required: true })
});
viewModel.invalidator('');
viewModel.invalidator('a');
},
submit: function() {
if (viewModel.errors.isValid()) {
alert('Thank you.');
}
else {
alert('Please check your submission. Errors: ' + viewModel.errors.errors().length);
viewModel.errors.errors.showAllMessages();
}
}
};
viewModel.errors = ko.validatedObservable({
items: viewModel.items,
test: viewModel.test,
invalidator: viewModel.invalidator
});

Kendo Grid calls 'create' operation instead of 'update' after adding new record

I've setup a basic Kendo Grid and I'm using the DataSourceResult class from the PHP Wrapper library on the sever side.
I've come across a strange issue... if I create a new record and then edit it (without refreshing the page), the create operation is called again, rather than the update operation.
If the page is refreshed after adding the new record, the update operation is called correctly after making changes to the record.
I can confirm that the DataSourceResult class is returning the correct data after the create operation, including the id of the new record.
Any ideas why this is happening (and how to stop it)?
Thanks
Update: Here's the datasource code. The query string in the url is just to easily distinguish the requests in Chrome's console. The additional data passed with each request is used by ajax.php to distinguish the different actions requested.
data = new kendo.data.DataSource({
transport: {
create: {
url: '/ajax.php?r=gridCreate',
dataType: 'json',
type: 'post',
data: { request: 'grid', type: 'create' }
},
read: {
url: '/ajax.php?request=gridRead',
dataType: 'json',
type: 'post',
data: { request: 'grid', type: 'read' }
},
update: {
url: '/ajax.php?r=gridUpdate',
dataType: 'json',
type: 'post',
data: { request: 'grid', type: 'update' }
},
destroy: {
url: '/ajax.php?r=gridDestroy',
dataType: 'json',
type: 'post',
data: { request: 'grid', type: 'destroy' }
},
parameterMap: function(data, operation) {
if (operation != "read"){
data.expires = moment(data.expires).format('YYYY-MM-DD HH:mm');
}
return data;
}
},
schema: {
data: 'data',
total: 'total',
model: {
id: 'id',
fields: {
id: { editable: false, nullable: true },
code: { type: 'string' },
expires: { type: 'date' },
enabled: { type: 'boolean', defaultValue: true }
}
}
},
pageSize: 30,
serverPaging: true,
serverSorting: true,
serverFiltering: true
});
Best solution
Set to update, create or delete different Call Action
From Telerik Support :
I already replied to your question in the support thread that you
submitted on the same subject. For convenience I will paste my reply
on the forum as well.
This problem occurs because your model does not have an ID. The model
ID is essential for editing functionality and should not be ommited -
each dataSource records should have unique ID, records with empty ID
field are considered as new and are submitted through the "create"
transport.
schema: {
model: {
//id? model must have an unique ID field
fields: {
FirstName: { editable: false},
DOB: { type: "date"},
Created: {type: "date" },
Updated: {type: "date" },
}
} },
For more information on the subject, please check the following
resources:
http://docs.kendoui.com/api/framework/model#methods-Model.define
http://www.kendoui.com/forums/ui/grid/request-for-support-on-editable-grid.aspx#228oGIheFkGD4v0SkV8Fzw
MasterLink
I hope this information will help
I have also the same problem & I have tried this & it will work.
.Events(events => events.RequestEnd("onRequestEnd"))
And in this function use belowe:
function onRequestEnd(e) {
var tmp = e.type;
if (tmp == "create") {
//RequestEnd event handler code
alert("Created succesully");
var dataSource = this;
dataSource.read();
}
else if (tmp == "update") {
alert("Updated succesully");
}
}
Try to Use this code in onRequestEnd event of grid
var dataSource = this;
dataSource.read();
Hope that it will help you.
Pass the auto-incremented id of the table when you call the get_data() method to display data into kendo grid, so that when you click on the delete button then Deledata() will call definitely.
Another variation, in my case, I had specified a defaultValue on my key field:
schema: $.extend(true, {}, kendo.data.transports["aspnetmvc-ajax"], {
data: "Data",
total: "Total",
errors: "Errors",
model: kendo.data.Model.define({
id: "AchScheduleID",
fields: {
AchScheduleID: { type: "number", editable: true, defaultValue: 2 },
LineOfBusinessID: { type: "number", editable: true },
Not sure what I was thinking but it caused the same symptom.

Kendo UI does not call create if a function is specified

Using Kendo.web.js versions 2013.2.716 and 2012.3.1315, I am trying to use a function in my transport.create rather than calling a URL. What I find is that the function does not get called. Instead a default URL is called and the resulting HTML appears to cause an error in the bowels of kendo because it is expected to be JSON instead.
I assume that this is some type of configuration error, but I can't figure out where the problem is.
Here is a snippet of the code:
var clientListDS = new kendo.data.DataSource({
transport: {
read: {
url: window.baseUrl + 'HealthCheck/ClientSummary',
dataType: 'json',
type: 'POST'
},
create: function(a,b,c) { alert('Create'); },
createY: window.baseUrl + 'HealthCheck/DontCallMe',
createX: {
url: window.baseUrl + 'HealthCheck/DontCallMe',
dataType: 'json',
type: 'POST'
},
whatWeWantCreateToDo: function () {
showChooseDialog('Some Random String', 'Select Client', OnRefreshInactiveClientList);
},
destroy: function () {
alert('destroy');
},
update: function () {
alert('update');
}
},
autoSync: true,
schema: {
model: {
id: 'ID',
fields: {
ID: { required: false, type: 'number', nullable: true },
ClientName: { type: 'string' },
ClientTag: { type: 'string' },
Status: { type: 'string' }
}
}
}
});
Then I use the resulting data source to build a grid like this:
$('#cClientGrid').kendoGrid({
dataSource: clientListDS,
columns: [
{ field: 'ClientTag', title: 'Tag'},
{ field: 'ClientName', title: 'Name' },
{ field: 'Status' }
],
editable: {
mode: 'incell',
createAt: 'bottom'
},
edit: function (pEvent) {
if (pEvent.model.isNew())
alert('create');
else
alert('Edit');
},
toolbar: ['create']
});
Some behavior that is worthy of note:
You see several attempts at the create configuration. If I use CreateY or CreateX, it will call the resulting URL. If I use Create or WhatWeWantCreateToDo, I end up downloading the containing page with each element of my schema as get string items (I assume this is some type of default behavior as I can't find a reference to the URL which is downloaded).
When I turn off autoSync, the grid will call its edit function when I use the toolbar to create a new item. When I turn on autoSync, the edit function does not get called. Instead the data source create functionality runs.
Any thoughts or insight on how I might be able to call a function instead of a URL will be appreciated.
First make in transport everything being an URL or a function, do not mix them up.
If you need to implement read as a function, you simply do:
transport: {
read : function (options) {
$.ajax({
url: window.baseUrl + 'HealthCheck/ClientSummary',
dataType: 'json',
type: 'POST',
success : function (result) {
options.success(result);
}
});
},

Knockout object passed to Controller as JSon MVC ASP.Net

I am trying to pass knockout object as below,
When i pass the data using // ko.utils.postJson only without any the AJAx the data is passed to my controller to the "task", but when i try to post by Ajax I get a null value for task
function TaskListViewModel() {
var self = this;
self.availableMeals = [
{ UserName: "Standard", UserId: 0 },
{ UserName: "Premium", UserId: 34 },
{ UserName: "Ultimate", UserId: 290 }
];
self.save = function () {
// ko.utils.postJson(location.href, { task: this.availableMeals });
$.ajax(location.href,{
data: ko.toJSON({ task: this.availableMeals });,
type: 'POST',
dataType:'json',
contentType: 'application/json',
success: function (result) { alert(result) }
});
};
}
ko.applyBindings(new TaskListViewModel());
To the Controller as below,
[HttpPost]
public ActionResult About([FromJson] IEnumerable<UserProfile> task)
{
return RedirectToAction("Login","Account");
}
I would try changing your code to call the stored self reference in your Ajax call as follows:
$.ajax(location.href,{
data: ko.toJSON({ task: self.availableMeals });,
type: 'POST',
dataType:'json',
contentType: 'application/json',
success: function (result) { alert(result) }
});
};
I'm guessing that you are having a scope issues where this is losing it's reference in your Ajax call.

Resources