kendoValidator how to add on to existing rule functionality - kendo-validator

I'm looking to add on to the kendoValidator required rule. I want it to function the same way but with one exception. Unfortunately once I provide a function for it in the rules section I have to code all the logic for the required function again.
wondering if there is a way to piggyback off the existing functionality of "required" rule. Currently the code below has everything marked required that isn't disabled, even if it has a value in it.
function runValidation() {
$(".dateTimePickerField").each(function () {
var validator = $(this).kendoValidator({
rules: {
required: function (e) {
if ($(e).is(':disabled'))
{
return true;
}
},
dateValidation: function (e) {
var dateTime = $(e).val();
var currentDate = Date.parse($(e).val());
if (dateTime.length > 0 && !currentDate) {
return false;
}
return true;
}
},
messages: {
//Define your custom validation massages
required: "datetime required",
dateValidation: "Invalid datetime"
}
}).data("kendoValidator");
validator.validate();
});
}

I just ended up coding the necessary logic for the required rule. It wasn't too difficult of a rule to code so i just did that.
function runValidation() {
var boolval = true;
$("input.dateTimePickerField").each(function () {
var validator = $(this).kendoValidator({
rules: {
required: function (e) {
if ($(e).prop('required')) {
if ($(e).is(':disabled') || $(e).val().length > 0) {
return true;
}
return false;
}
return true;
},
dateValidation: function (e) {
var dateTime = $(e).val();
var currentDate = Date.parse($(e).val());
if (dateTime.length > 0 && !currentDate) {
return false;
}
return true;
},
customEventDateValidation: function (e) {
var dateTime = $(e).val();
var currentDate = Date.parse($(e).val());
var row = $(e).closest('tr');
var startDateText = row.find(".startDate").text();
var eventStartDate = Date.parse(startDateText);
if (currentDate && eventStartDate)
{
if(currentDate > eventStartDate)
{
return false;
}
}
return true;
},
customTicketStartDateValidation: function (e) {
if ($(e).hasClass("ticketStartDate"))
{
var dateTime = $(e).val();
var currentDate = Date.parse($(e).val());
var row = $(e).closest('tr');
var ticketEndDateText = row.find("input.ticketEndDate").val();
var ticketEndDate = Date.parse(ticketEndDateText);
if(currentDate && ticketEndDate)
{
if(currentDate > ticketEndDate)
{
return false;
}
}
}
return true;
},
customTicketEndDateValidation: function (e) {
if ($(e).hasClass("ticketEndDate")) {
var dateTime = $(e).val();
var currentDate = Date.parse($(e).val());
var row = $(e).closest('tr');
var ticketStartDateText = row.find("input.ticketStartDate").val();
var ticketStartDate = Date.parse(ticketStartDateText);
if (currentDate && ticketStartDate) {
if (currentDate < ticketStartDate) {
return false;
}
}
}
return true;
}
},
messages: {
required: "Datetime required",
dateValidation: "Invalid datetime",
customEventDateValidation: "Datetime must be before event date",
customTicketStartDateValidation: "Ticket start datetime must be before ticket end datetime",
customTicketEndDateValidation: "Ticket end datetime must be after ticket start datetime"
}
}).data("kendoValidator");
if (!validator.validate()) {
boolval = false;
}
});
return boolval;
}

Related

How to add my textbox item in the table? in master detail form

I am using MVC to create my Master Detail form, i have tried this to add my detail record in the to show my detail record in the form so that when user click Add button detail data itself shows in a table.
JQUERY is not working
This is my View:
#section script{
//date picker
$(function () {
$('#orderDate').datepicker({
datepicker: 'mm-dd-yy'
});
});
$(document).ready(function()
{
var orderItems = [];
//Add Button click function
$('#add').click(function () {
//Chk Validation
var isValidItem = true;
if ($('#itemName').val().trim() == '') {
isValidItem = false;
$('#itemName').siblings('span.error').css('visibility', 'vissible')
}
else {
$('#itemName').siblings('span.error').css('visibility', 'hidden')
}
if (!($('#quantity').val().trim() !== '' && !isNaN($('#dvch_nar').val().trim()))) {
isValidItem = false;
$('#quantity').siblings('span.error').css('visibility', 'vissible')
}
else {
$('#quantity').siblings('span.error').css('visibility', 'hidden')
}
if (!($('#itemName').val().trim() !== '' && !isNaN($('#dvch_cr_amt').val().trim()))) {
isValidItem = false;
$('#itemName').siblings('span.error').css('visibility', 'vissible')
}
else {
$('#itemName').siblings('span.error').css('visibility', 'hidden')
}
if (!($('#rate').val().trim() !== '' && !isNaN($('#dvch_cr_amt').val().trim()))) {
isValidItem = false;
$('#rate').siblings('span.error').css('visibility', 'vissible')
}
else {
$('#rate').siblings('span.error').css('visibility', 'hidden')
}
//add item to list if valid
if (isValidItem) {
orderItems.push(
{
ItemName: $('#itemName').val().trim(),
Quantity:parseInt$('#quantity').val().trim(),
Rate: parseInt$('#rate').val().trim(),
Total: parseInt($('#quantity').val().trim())* parseFloat($('#rate').val().trim())
});
//clear fields
$('#itemName').val('').focus();
$('#quantity').val('');
$('#rate').val('');
}
//populate order item
GeneratedItemsTable();
}
);
//save button click function
$('#submit').click(function () {
//validation order
var isAllValid = true;
if(orderItems.length=0)
{
$('#orderItems').html('<span style="color:red;">Please add another item</span>')
isAllValid = false;
}
if ($('#orderNo').val().trim() == '')
{
$('#orderNo').siblings('span.error').css('visibility', 'visible')
isAllValid = false;
}
else {
$('#orderNo').siblings('span.error').css('visibility', 'hidden')
}
if ($('#orderDate').val().trim() == '') {
$('#orderDate').siblings('span.error').css('visibility', 'visible')
isAllValid = false;
}
else {
$('#orderDate').siblings('span.error').css('visibility', 'hidden')
}
//if ($('')
//save if valid
if (isAllValid){
var data={
Date: $('#orderNo').val().trim(),
Remarks: ('#orderDate').val().trim(),
Description:$('description').val().trim(),
orderDetails:orderItems
}
}
$(this).val("Please Wait...");
$.ajax(
{
url: "/Home/SaveOrder",
type:"post",
data:JSON.stringify(data),
dataType:"application/json",
success:function(d){
//check is successfully save to database
if(d.status==true)
{
//will send status from server side
alert('successfully done.');
//clear form
orderItems=[];
$('#orderNo').val('');
$('#orderDate').val('');
$('#orderItems').empty();
}
else{
alert('Failed');
}
},
error :function(){
alert('Error:Please Try again.');
}
}
);
});
//function for show added item
function GeneratedItemsTable()
{
if(orderItems.length>0)
{
var $table = $('<table/>');
$table.append('<thead><tr><th>Item</th><th>Quantity</th><th>Rate</th><th>Total</th></tr></thead>')
var $tboday = $('<tbody/>');
$.each(orderItems,function(i,val)
{
var $row=$('<tr/>');
$row.append($('<tr/>').html(val.ItemName))
$row.append($('<tr/>').html(val.Quantity))
$row.append($('<tr/>').html(val.Rate))
$row.append($('<tr/>').html(val.Total))
$tboday.append($row);
});
$table.append($tboday);
$('#orderItems').html($table);
}
}
}
);
</script>
}
thanks for quick response
Try this
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<script>
//Date Picker
$(function () {
$('#orderDate').datepicker({
dateFormat : 'mm-dd-yy'
});
});
$(document).ready(function () {
var orderItems = [];
//Add button click function
$('#add').click(function () {
//Check validation of order item
var isValidItem = true;
if ($('#itemName').val().trim() == '') {
isValidItem = false;
$('#itemName').siblings('span.error').css('visibility', 'visible');
}
else {
$('#itemName').siblings('span.error').css('visibility', 'hidden');
}
if (!($('#quantity').val().trim() != '' && !isNaN($('#quantity').val().trim()))) {
isValidItem = false;
$('#quantity').siblings('span.error').css('visibility', 'visible');
}
else {
$('#quantity').siblings('span.error').css('visibility', 'hidden');
}
if (!($('#rate').val().trim() != '' && !isNaN($('#rate').val().trim()))) {
isValidItem = false;
$('#rate').siblings('span.error').css('visibility', 'visible');
}
else {
$('#rate').siblings('span.error').css('visibility', 'hidden');
}
//Add item to list if valid
if (isValidItem) {
orderItems.push({
ItemName: $('#itemName').val().trim(),
Quantity: parseInt($('#quantity').val().trim()),
Rate: parseFloat($('#rate').val().trim()),
TotalAmount: parseInt($('#quantity').val().trim()) * parseFloat($('#rate').val().trim())
});
//Clear fields
$('#itemName').val('').focus();
$('#quantity,#rate').val('');
}
//populate order items
GeneratedItemsTable();
});
//Save button click function
$('#submit').click(function () {
//validation of order
var isAllValid = true;
if (orderItems.length == 0) {
$('#orderItems').html('<span style="color:red;">Please add order items</span>');
isAllValid = false;
}
if ($('#orderNo').val().trim() == '') {
$('#orderNo').siblings('span.error').css('visibility', 'visible');
isAllValid = false;
}
else {
$('#orderNo').siblings('span.error').css('visibility', 'hidden');
}
if ($('#orderDate').val().trim() == '') {
$('#orderDate').siblings('span.error').css('visibility', 'visible');
isAllValid = false;
}
else {
$('#orderDate').siblings('span.error').css('visibility', 'hidden');
}
//Save if valid
if (isAllValid) {
var data = {
OrderNo: $('#orderNo').val().trim(),
OrderDate: $('#orderDate').val().trim(),
//Sorry forgot to add Description Field
Description : $('#description').val().trim(),
OrderDetails : orderItems
}
$(this).val('Please wait...');
$.ajax({
url: '/Home/SaveOrder',
type: "POST",
data: JSON.stringify(data),
dataType: "JSON",
contentType: "application/json",
success: function (d) {
//check is successfully save to database
if (d.status == true) {
//will send status from server side
alert('Successfully done.');
//clear form
orderItems = [];
$('#orderNo').val('');
$('#orderDate').val('');
$('#orderItems').empty();
}
else {
alert('Failed');
}
$('#submit').val('Save');
},
error: function () {
alert('Error. Please try again.');
$('#submit').val('Save');
}
});
}
});
//function for show added items in table
function GeneratedItemsTable() {
if (orderItems.length > 0)
{
var $table = $('<table/>');
$table.append('<thead><tr><th>Item</th><th>Quantity</th><th>Rate</th><th>Total</th><th></th></tr></thead>');
var $tbody = $('<tbody/>');
$.each(orderItems, function (i, val) {
var $row = $('<tr/>');
$row.append($('<td/>').html(val.ItemName));
$row.append($('<td/>').html(val.Quantity));
$row.append($('<td/>').html(val.Rate));
$row.append($('<td/>').html(val.TotalAmount));
var $remove = $('Remove');
$remove.click(function (e) {
e.preventDefault();
orderItems.splice(i, 1);
GeneratedItemsTable();
});
$row.append($('<td/>').html($remove));
$tbody.append($row);
});
console.log("current", orderItems);
$table.append($tbody);
$('#orderItems').html($table);
}
else {
$('#orderItems').html('');
}
}
});
</script>

How to stop Kendo UI dropdown from sorting alphabetically

I have been given the fun job on taking on someone elses code and trying to figure it out...
I have been tearing my hair out trying to figure out how to to stop a Kendo UI dropdown from sorting alphabetically ?
<select id="ddlArtworkStatuses" onlyPreparedValues="true"
readOnlyInput="true" data-bind="idNameOptions: artworkStatuses,
comboboxSelectedValue: artworkStatusId"></select>
For some reason this sorts althabetically but I want it to keep the order in the datasource. I have double checked to make sure it is in the order I want.
It doesn't use the standard way of using Kendo UI and I can't find any examples anywhere of using it this way?
It binds the view to the model with this line at the top of the view I believe?
<!-- ko with: fabricationModel -->
The vm.fabrication file is this:
(function (app) {
app.namespace("models");
var resources = {
unableToDeleteArtworkMessage: "This artwork cannot be deleted because it is linked to one or more of the following: Movements, Shows, POs. Or it has Imported Costs, Sales or Restoration Cases.",
unableToBlankArtworkFullyMessage: "This artwork has some data that will not be blanked if you continue. This could be one or more of the following: Movements, Shows, POs, Imported Costs, Sales or Restoration Cases. Do you want to continue?",
deleteArtworkTitle: "Delete artwork",
blankArtworkTitle: "Blank Artwork",
duplicateTitle: "New artwork form is pre-populated",
duplicateMessage: "You can make changes to Fabrication form fields. Record will be created after you press save button",
saveError: 'An error occured during artwork saving. Changes were not saved.'
};
app.models.FabricationModel = function (datasource) {
var emitter = new app.events.EventEmitter(),
self = this,
duplicateArtwork = ko.observable(false);
this.isNewArtwork = ko.observable(false);
this.isActivated = ko.observable(false);
this.showCreationInformation = ko.observable(true);
this.wipeArtworkModel = new app.models.WipeArtworkDialogModel(datasource);
this.internalArtworkModel = ko.observable();
this.editCategoryModel = new app.models.EditDhCategoryModel();
// alert("data=" + this.artworkStatuses);
this.isReadOnly = ko.computed(function () {
if (!self.internalArtworkModel()) {
return true;
}
return self.internalArtworkModel().isReadOnly();
});
this.canSaveStudioStatusOnly = ko.computed(function () {
if (!self.internalArtworkModel()) {
return false;
}
return self.internalArtworkModel().isUnblockStatusActive()
&& self.internalArtworkModel().isReadOnly()
&& self.internalArtworkModel().isStudioStatusVisible();
});
this.canSaveCatRaisOnly = ko.computed(function () {
if (!self.internalArtworkModel()) {
return false;
}
return self.internalArtworkModel().isReadOnly()
&& self.internalArtworkModel().isArchiveProvenanceWriter();
});
this.isNewOrDuplicating = ko.computed(function () {
return self.isNewArtwork() || duplicateArtwork();
});
this.activate = function (params) {
var id = params.id || 0;
self.isNewArtwork(!id);
return self.loadArtworkDetails(id);
};
this.isValid = function () {
return self.internalArtworkModel() && self.internalArtworkModel().errors().length == 0;
};
this.loadArtworkDetails = function (id) {
var action = self.isNewArtwork() ? datasource.artworks.getEmpty : datasource.artworks.getById;
return action(id)
.done(function (result) {
var mapper = app.mappers["fabrication"],
model = mapper.map(result.data);
self.internalArtworkModel(model);
self.editCategoryModel.categoryId(model.defaultDhCategoryId);
self.editCategoryModel.setModeAsCategoryChanging();
if (self.isNewArtwork()) {
self.editCategoryModel.setModeAsCreation();
self.editCategoryModel.show();
}
self.isActivated(true);
duplicateArtwork(false);
$("a#science-link").attr("href", window.location.href);
triggerLoadEvent();
});
};
this.saveArtwork = function () {
if (self.isValid()) {
return saveInternal($.noop);
}
};
this.editCategory = function () {
self.editCategoryModel.show();
};
this.onLoad = function (callback) {
emitter.subscribe("load", callback);
};
this.onCategoryChanged = function (callback) {
emitter.subscribe("category-changed", callback);
};
this.onDelete = function (callback) {
emitter.subscribe("delete", callback);
};
this.onCreated = function (callback) {
emitter.subscribe("artwork-created", callback);
};
this.onUpdated = function (callback) {
emitter.subscribe("artwork-updated", callback);
};
this.onBlanked = function (callback) {
emitter.subscribe("blanked", callback);
};
this.saveStudioStatusInt = function () {
return saveStudioStatusInternal($.noop);
};
this.saveCatRaisInt = function () {
return saveCatRaisInternal($.noop);
};
this.saveStudioStatus = ko.asyncCommand({
execute: function (complete) {
saveStudioStatusInternal(complete);
},
canExecute: function (isExecuting) {
return !isExecuting && self.canSaveStudioStatusOnly();
}
});
this.saveCatRais = ko.asyncCommand({
execute: function (complete) {
saveCatRaisInternal(complete);
},
canExecute: function (isExecuting) {
return !isExecuting && self.canSaveCatRaisOnly();
}
});
this.save = ko.asyncCommand({
execute: function (complete) {
return saveInternal(complete);
},
canExecute: function (isExecuting) {
if (!self.isValid()) {
showErrors();
}
return !isExecuting && self.isValid();
}
});
function saveStudioStatusInternal(completeCallback) {
var model = self.internalArtworkModel();
triggerSaveStudioStatusEvent();
datasource.artworks.saveStudioStatus(model.artworkId(), model.artworkStatusId(), model.studioStatusId).always(completeCallback);
}
function saveCatRaisInternal(completeCallback) {
var model = self.internalArtworkModel();
triggerSaveStudioStatusEvent();
datasource.artworks.saveCatRais(model.artworkId(), model.inclusion(), model.image(), model.details(), model.crReady(), model.selectedVolume.selected.value).always(completeCallback);
}
this.onSaveStudioStatus = function (callback) {
emitter.subscribe("saveStudioStatus", callback);
};
function triggerSaveStudioStatusEvent() {
emitter.publish("saveStudioStatus");
}
this.beginArtworkDeletion = function () {
if (!self.internalArtworkModel().canBeBlanked) {
jAlert(resources.unableToDeleteArtworkMessage, resources.deleteArtworkTitle);
return;
}
self.wipeArtworkModel.beginArtworkDeletion(self.internalArtworkModel().artworkId());
};
this.beginArtworkBlanking = function () {
if (!self.internalArtworkModel().canBeBlanked) {
//jAlert(resources.unableToBlankArtworkMessage, resources.blankArtworkTitle);
app.alerts.appConfirm(resources.unableToBlankArtworkFullyMessage, resources.blankArtworkTitle, function (ok) {
if (ok) {
self.wipeArtworkModel.beginArtworkBlanking(self.internalArtworkModel().artworkId());
}
});
return;
}
self.wipeArtworkModel.beginArtworkBlanking(self.internalArtworkModel().artworkId());
};
this.duplicateArtwork = function () {
if (!self.internalArtworkModel()) {
return;
}
duplicateArtwork(true);
resetModelBeforeDuplication();
if (self.isValid()) {
showErrors();
}
jAlert(resources.duplicateMessage, resources.duplicateTitle);
};
function saveInternal(completeCallback) {
var mapper = app.mappers["fabrication"];
//alert("saving now...");
var unmappedModel = mapper.toJS(self.internalArtworkModel());
if (duplicateArtwork()) {
return saveDuplicatedArtwork(unmappedModel, completeCallback);
}
if (unmappedModel.artworkId) {
return updateArtwork(unmappedModel, completeCallback);
}
return createArtwork(unmappedModel, completeCallback);
}
function saveDuplicatedArtwork(model, completeCallback) {
return datasource.artworks.duplicate(model)
.always(completeCallback)
.fail(function (response) {
jAlert(resources.saveError);
})
.done(function (id) {
triggerArtworkCreatedEvent(id);
duplicateArtwork(false);
self.showCreationInformation(true);
});
}
function updateArtwork(model, completeCallback) {
return datasource.artworks.save(model)
.always(completeCallback)
.fail(function (response) {
jAlert(resources.saveError);
})
.done(function (result) {
if (!result) {
return;
}
var mapper = app.mappers["fabrication"],
mappedModel = mapper.map(result.data);
triggerUpdateEvent(
{
dhCategory: mappedModel.dhCategory(),
refNumber: mappedModel.refNumber(),
computedTitle: mappedModel.computedTitle()
});
self.internalArtworkModel(mappedModel);
});
}
function createArtwork(model, completeCallback) {
return datasource.artworks.save(model)
.always(completeCallback)
.fail(function (response) {
jAlert(resources.saveError);
})
.done(function (id) {
if (id) {
triggerArtworkCreatedEvent(id);
}
});
}
function triggerLoadEvent() {
var model = self.internalArtworkModel();
emitter.publish("load", {
artworkId: model.artworkId() || 0,
dhCategory: model.dhCategory() || "",
refNumber: model.refNumber() || "",
computedTitle: model.computedTitle() || "",
isForSale: model.isForSale
});
}
function triggerArtworkCreatedEvent(artworkId) {
emitter.publish("artwork-created", artworkId);
}
function triggerCategoryChangedEvent() {
emitter.publish("category-changed", {
name: self.internalArtworkModel().dhCategoryName(),
id: self.internalArtworkModel().dhCategoryId()
});
}
function triggerDeleteEvent(e, artworkId) {
emitter.publish("delete", artworkId);
}
function triggerUpdateEvent(data) {
var model = self.internalArtworkModel();
data.isCategoryChanged = model.initialCategoryId !== model.dhCategoryId();
emitter.publish("artwork-updated", data);
}
function showErrors() {
var model = self.internalArtworkModel();
if (model) {
model.errors.showAllMessages();
}
}
function resetModelBeforeDuplication() {
var model = self.internalArtworkModel();
model.refNumber("");
model.computedTitle("");
model.isOnDisplay(false);
model.isOnRestoration(false);
model.salesStatus("Not set");
model.creationDate("");
model.creatorName("");
model.isFramed(false);
model.framedDate("");
model.framedUserName("");
model.framedUserInitials("");
model.framedUserId(null);
model.locations(null);
model.isInsuranceComponent(false);
model.dateWebsiteWork("");
model.dateWebsiteReady("");
model.dateWebsiteUploaded("");
model.dateRemovedFromWebsite("");
model.collectionListing("");
model.salesStatusChangedDate("");
model.salesStatusChangerUserInitials("");
model.salesStatusChangerUserName("");
self.showCreationInformation(false);
}
function triggerBlanked(artworkId) {
emitter.publish("blanked", { artworkId: artworkId, flag: true });
}
(function () {
self.editCategoryModel.onChanged(function (e, categoryId) {
self.internalArtworkModel().dhCategoryId(categoryId);
triggerCategoryChangedEvent();
});
self.editCategoryModel.onCancel(function () {
if (self.isNewArtwork()) {
self.isNewArtwork(false);
app.router.back();
}
});
self.wipeArtworkModel.onDelete(triggerDeleteEvent);
self.wipeArtworkModel.onBlank(function (e, artworkId) {
self.loadArtworkDetails(artworkId);
triggerBlanked(artworkId);
});
})();
};
})(app);
It also uses a mapper:
(function (app, ko) {
app.namespace("mappers");
var s = app.urls.shared,
datasource = app.datasource;
var mapSettings = {
selectedMedium: {
create: function (options) {
return new ListModel({
isRemoteSource: true,
url: s.get('dictionaryUrl'),
listType: datasource.dictionaryTypes.get("medium"),
currentValue: options.data,
nobutton: true,
templateName: "textAreaTemplate"
});
}
},
artist: {
create: function (options) {
return new ListModel({
isRemoteSource: true,
url: s.get('dictionaryUrl'),
listType: datasource.dictionaryTypes.get("artist"),
currentValue: options.data,
onlyPreparedValues: false
});
}
},
manager: {
create: function (options) {
return new ListModel({
isRemoteSource: true,
url: s.get('dictionaryUrl'),
listType: datasource.dictionaryTypes.get("manager"),
currentValue: options.data,
onlyPreparedValues: false
});
}
},
managerStatus: {
create: function (options) {
return new ListModel({
isRemoteSource: true,
url: s.get('dictionaryUrl'),
listType: datasource.dictionaryTypes.get("managerStatus"),
currentValue: options.data,
onlyPreparedValues: false
});
}
},
selectedVolume: {
create: function (options) {
return new ListModel({
isRemoteSource: true,
url: s.get('dictionaryUrl'),
listType: datasource.dictionaryTypes.get("volume"),
currentValue: options.data,
onlyPreparedValues: false,
readonly: !options.parent.isArchiveProvenanceWriter(),
editable: options.parent.isArchiveProvenanceWriter()
});
}
},
salesStatus: {
create: function (options) {
var value = options.data || "Not set";
return ko.observable(value);
}
},
oldReferences: {
create: function (options) {
return ko.observable(options.data);
}
},
copy: ['defaultDhCategoryId', "canBeDeleted", "canBeBlanked", "isForSale"],
ignore: ["dimensions", "dimensionUnits", "selectedMediumTypes", "selectedSeries", "selectedSubSeries", "selectedAkaNames", "selectedWebSiteMediumTypes", 'selectedWebSiteCategoryIds', "locations", "hasInTransitLocations"]
},
unmapSettings = {
ignore: ["selectedMedium", "artist", "manager", "managerStatus", "mediumTypesModel", "dimensionModel", "seriesModel", "subSeriesModel", "akaModel", "webSiteMediumTypesModel", "webSiteCategoriesModel", "selectedVolume"]
},
map = function (json) {
var convertedObject = ko.utils.parseJson(json);
var model = ko.mapping.fromJS(convertedObject, mapSettings);
model.artworkStatusesModel = new ListModel({
isRemoteSource: false,
currentValue: convertedObject.selectedArtworkStatus,
data: convertedObject.artworkStatuses,
//data: filteredSalesStatuses,
onlyPreparedValues: true,
allowNull: false,
readonly: true
});
alert("mooo=" + model.artworkStatuses()[0].name());
alert("mooo=" + model.artworkStatuses()[1].name());
alert("mooo=" + model.artworkStatuses()[2].name());
//alert("mooo=" + model.artworkStatuses()[3].name());
//alert("mooo=" + model.artworkStatuses()[4].name());
model.dhCategoryName = ko.computed(function () {
var categories = model.dhCategories();
for (var i = 0; i < categories.length; i++) {
var category = categories[i];
if (category.id() == model.dhCategoryId()) {
return category.name();
}
}
return "";
});
model.initialCategoryId = convertedObject.dhCategoryId;
model.dimensionModel = new app.models.DimensionModel(convertedObject.dimensions);
ko.utils.arrayForEach(convertedObject.dimensionUnits, function (unit) {
model.dimensionModel.units.push(unit);
});
model.locations = ko.observable(convertedObject.locations ? {
archivedLocations: $.map(convertedObject.locations, function (elem) {
return elem.isArchived ? elem : null;
}),
activeLocations: $.map(convertedObject.locations, function (elem) {
return elem.isArchived ? null : elem;
}),
hasInTransitLocations: convertedObject.hasInTransitLocations
} : convertedObject.locations);
model.mediumTypesModel = new app.models.MultilistModel(convertedObject.selectedMediumTypes, { url: s.get("mediumTypesUrl") });
model.seriesModel = new app.models.MultilistModel(convertedObject.selectedSeries, { url: s.get("seriesUrl") });
model.subSeriesModel = new app.models.MultilistModel(convertedObject.selectedSubSeries, { url: s.get("subSeriesUrl") });
model.akaModel = new app.models.MultilistModel(convertedObject.selectedAkaNames, { url: s.get("akaUrl") });
model.webSiteMediumTypesModel = new app.models.MultilistModel(convertedObject.selectedWebSiteMediumTypes, { url: s.get("webSiteMediumTypeUrl") });
model.webSiteCategoriesModel = new app.models.MultilistModel(convertedObject.selectedWebSiteCategories, { url: s.get("webSiteCategoryUrl") });
model.isStudioStatusVisible = ko.computed(function () {
var foundStatuses = ko.utils.arrayFilter(model.artworkStatuses(), function (status) {
return status.id() == model.artworkStatusId();
});
var currentStatus = foundStatuses[0];
if (currentStatus) {
return currentStatus.name().toLowerCase() == "in progress";
}
return false;
});
addValidationOptions(model);
return model;
},
toJS = function (artwork) {
var result = ko.mapping.toJS(artwork, unmapSettings);
result.artist = artwork.artist.toJS();
result.manager = artwork.manager.toJS();
result.managerStatus = artwork.managerStatus.toJS();
result.selectedMedium = artwork.selectedMedium.toJS();
result.selectedVolume = artwork.selectedVolume.toJS();
result.dimensions = artwork.dimensionModel.toJS();
result.selectedMediumTypes = artwork.mediumTypesModel.toJS();
result.selectedSeries = artwork.seriesModel.toJS();
result.selectedSubSeries = artwork.subSeriesModel.toJS();
result.selectedAkaNames = artwork.akaModel.toJS();
result.selectedWebSiteMediumTypes = artwork.webSiteMediumTypesModel.toJS();
result.selectedWebSiteCategories = artwork.webSiteCategoriesModel.toJS();
return result;
};
function isValidationRequired(model) {
var artworkStatus = ko.utils.unwrapObservable(model.artworkStatusId);
var dhCategory = ko.utils.unwrapObservable(model.dhCategoryId);
return artworkStatus == app.global.dictionary.get("compiteArtworkStatus")
&& dhCategory != app.global.dictionary.get("ignoreDHCatigory");
}
function addValidationOptions(model) {
model.artworkStatusId.extend({ required: true });
model.title.extend({ required: true });
model.artist.selected.value.extend({ required: true });
model.startYear.extend({
lessEqualThan: {
params: model.endYear,
onlyIf: function () {
return (model.endYear() != undefined && model.endYear() != null);
},
message: 'From Date should be less or equal than a To Date'
}
});
model.endYear.extend({
required: {
params: true,
onlyIf: function () {
return isValidationRequired(model);
},
message: "To Date field is required"
}
});
model.selectedMedium.selected.value.extend({
required: {
params: true,
onlyIf: function () {
return isValidationRequired(model);
},
message: "Medium is required"
}
});
model.mediumTypesModel.hasValue.extend({
equal: {
params: true,
onlyIf: function () {
return isValidationRequired(model);
},
message: "Medium Type is required"
}
});
model.akaModel.hasValue.extend({
equal: {
params: true,
onlyIf: function () {
return isValidationRequired(model);
},
message: "Aka is required"
}
});
model.isInsuranceComponent.extend({
equal: {
params: true,
onlyIf: function () {
return isValidationRequired(model);
},
message: "At least 1 Insurance component should be chosen"
}
});
model.dimensionModel.hasDimensions.extend({
equal: {
params: true,
onlyIf: function () {
return isValidationRequired(model);
},
message: "The Dimension fields should be filled"
}
});
model.errors = ko.validation.group(model, { deep: true });
}
app.mappers.fabrication = {
settings: mapSettings,
map: map,
toJS: toJS
};
})(app, ko);
Where I have the alerts, the items are in the right order, so somewhere they are getting sorted but cant find out where?!
I hope someone can help?
It would be really appreciated.
Many thanks,
David.

nightwatch assert ALL elements, not ANY

I'm trying to test that, when the Submit button is clicked on an empty form, all the "please fill in this field" labels are displayed.
I'm doing so with this:
page.click('#btn_submit');
page.expect.element('#validation_label_required').to.be.visible;
where #validation_label_required is represented by the CSS selector:
input[required] ~ p.error-message-required
However, this test passes if ANY of the validation labels are visible. The test should only pass if they ALL are.
How can I achieve this?
You will need to create a custom assertion for that where you locate all elements by selenium commands and then loop to verify condition. It should look something like this
var util = require('util');
exports.assertion = function (elementSelector, expectedValue, msg) {
this.message = msg || util.format('Testing if elements located by "%s" are visible', elementSelector);
this.expected = expectedValue;
this.pass = function (value) {
return value === this.expected;
};
this.value = function (result) {
return result;
};
this.command = function (callback) {
var that = this.api;
this.api.elements('css selector',elementSelector, function (elements) {
elements.value.forEach(function(element){
that.elementIdDisplayed(element.ELEMENT,function(result){
if(!result.value){
callback(false);
}
});
});
callback(true);
});
return this;
};
};
I've just ended up with another custom assertion that check how many elements are visible by given css selector.
/**
* Check how many elements are visible by given css selector.
*
*/
var util = require('util');
exports.assertion = function(elementSelector, expectedCount, msg) {
this.message = msg || util.format('Asserting %s elements located by css selector "%s" are visible', expectedCount, elementSelector);
this.expected = expectedCount;
this.count = 0;
this.pass = function(value) {
return value === this.expected;
};
this.value = function(result) {
return this.count;
};
this.command = function(callback) {
var me = this, elcount = 0;
this.count = 0;
this.api.elements('css selector', elementSelector, function(elements) {
if(elements.value && elements.value.length > 0){
elcount = elements.value.length;
}else{
return callback(false);
}
elements.value.forEach(function(element) {
me.api.elementIdDisplayed(element.ELEMENT, function(result) {
if (result.value) {
me.count++;
}
elcount--;
if (elcount === 0) {
callback(me.count);
}
});
});
});
};
};

Cached data returned when making same Web API call consecutively using Breeze.js

I am facing a strange issue while writing a Breeze.js with Durandal SPA (largely based on John Papa's Great SPA Jumpstart (https://github.com/johnpapa/PluralsightSpaJumpStartFinal) training ), the issue when a try to make the same server API call multiple times consecutively the server is hit only once and one the second call it seems I get cached data (call doesn't even hit server), this can be replicated in Jumpstart sample too, below is the modified code to replicate this on Jumpstart
var activate = function () {
for (var i = 0 ; i < 2 ; i++) {
datacontext.getSessionPartials(sessions, true);
}
};
var activate = function () {
for (var i = 0 ; i < 2 ; i++)
{
datacontext.getSpeakerPartials(speakers, true);
}
};
Edit- Updated with the complete code :
Code of my Viewmodel
define(['services/datacontext'], function (datacontext) {
var speakers = ko.observableArray();
var activate = function () {
for (var i = 0 ; i < 2 ; i++)
{
datacontext.getSpeakerPartials(speakers, true);
}
};
var refresh = function () {
return datacontext.getSpeakerPartials(speakers, true);
};
var vm = {
activate: activate,
speakers: speakers,
title: 'Speakers',
refresh: refresh
};
return vm;
});
Below is code of my datacontext/service :
define([
'durandal/system',
'services/model',
'config',
'services/logger',
'services/breeze.partial-entities'],
function (system, model, config, logger, partialMapper) {
var EntityQuery = breeze.EntityQuery;
var manager = configureBreezeManager();
var orderBy = model.orderBy;
var entityNames = model.entityNames;
var getSpeakerPartials = function (speakersObservable, forceRemote) {
if (!forceRemote) {
var p = getLocal('Persons', orderBy.speaker);
if (p.length > 0) {
speakersObservable(p);
return Q.resolve();
}
}
var query = EntityQuery.from('Speakers')
.select('id, firstName, lastName, imageSource')
.orderBy(orderBy.speaker);
return manager.executeQuery(query)
.then(querySucceeded)
.fail(queryFailed);
function querySucceeded(data) {
var list = partialMapper.mapDtosToEntities(
manager, data.results, entityNames.speaker, 'id');
if (speakersObservable) {
speakersObservable(list);
}
log('Retrieved [Speaker] from remote data source',
data, true);
}
};
var getSessionPartials = function (sessionsObservable, forceRemote) {
if (!forceRemote) {
var s = getLocal('Sessions', orderBy.session);
if (s.length > 3) {
// Edge case
// We need this check because we may have 1 entity already.
// If we start on a specific person, this may happen. So we check for > 2, really
sessionsObservable(s);
return Q.resolve();
}
}
var query = EntityQuery.from('Sessions')
.select('id, title, code, speakerId, trackId, timeSlotId, roomId, level, tags')
.orderBy('timeSlotId, level, speaker.firstName');
return manager.executeQuery(query)
.then(querySucceeded)
.fail(queryFailed);
function querySucceeded(data) {
var list = partialMapper.mapDtosToEntities(
manager, data.results, entityNames.session, 'id');
if (sessionsObservable) {
sessionsObservable(list);
}
log('Retrieved [Sessions] from remote data source',
data, true);
}
};
var getSessionById = function(sessionId, sessionObservable) {
// 1st - fetchEntityByKey will look in local cache
// first (because 3rd parm is true)
// if not there then it will go remote
return manager.fetchEntityByKey(
entityNames.session, sessionId, true)
.then(fetchSucceeded)
.fail(queryFailed);
// 2nd - Refresh the entity from remote store (if needed)
function fetchSucceeded(data) {
var s = data.entity;
return s.isPartial() ? refreshSession(s) : sessionObservable(s);
}
function refreshSession(session) {
return EntityQuery.fromEntities(session)
.using(manager).execute()
.then(querySucceeded)
.fail(queryFailed);
}
function querySucceeded(data) {
var s = data.results[0];
s.isPartial(false);
log('Retrieved [Session] from remote data source', s, true);
return sessionObservable(s);
}
};
var cancelChanges = function() {
manager.rejectChanges();
log('Canceled changes', null, true);
};
var saveChanges = function() {
return manager.saveChanges()
.then(saveSucceeded)
.fail(saveFailed);
function saveSucceeded(saveResult) {
log('Saved data successfully', saveResult, true);
}
function saveFailed(error) {
var msg = 'Save failed: ' + getErrorMessages(error);
logError(msg, error);
error.message = msg;
throw error;
}
};
var primeData = function () {
var promise = Q.all([
getLookups(),
getSpeakerPartials(null, true)])
.then(applyValidators);
return promise.then(success);
function success() {
datacontext.lookups = {
rooms: getLocal('Rooms', 'name', true),
tracks: getLocal('Tracks', 'name', true),
timeslots: getLocal('TimeSlots', 'start', true),
speakers: getLocal('Persons', orderBy.speaker, true)
};
log('Primed data', datacontext.lookups);
}
function applyValidators() {
model.applySessionValidators(manager.metadataStore);
}
};
var createSession = function() {
return manager.createEntity(entityNames.session);
};
var hasChanges = ko.observable(false);
manager.hasChangesChanged.subscribe(function(eventArgs) {
hasChanges(eventArgs.hasChanges);
});
var datacontext = {
createSession: createSession,
getSessionPartials: getSessionPartials,
getSpeakerPartials: getSpeakerPartials,
hasChanges: hasChanges,
getSessionById: getSessionById,
primeData: primeData,
cancelChanges: cancelChanges,
saveChanges: saveChanges
};
return datacontext;
//#region Internal methods
function getLocal(resource, ordering, includeNullos) {
var query = EntityQuery.from(resource)
.orderBy(ordering);
if (!includeNullos) {
query = query.where('id', '!=', 0);
}
return manager.executeQueryLocally(query);
}
function getErrorMessages(error) {
var msg = error.message;
if (msg.match(/validation error/i)) {
return getValidationMessages(error);
}
return msg;
}
function getValidationMessages(error) {
try {
//foreach entity with a validation error
return error.entitiesWithErrors.map(function(entity) {
// get each validation error
return entity.entityAspect.getValidationErrors().map(function(valError) {
// return the error message from the validation
return valError.errorMessage;
}).join('; <br/>');
}).join('; <br/>');
}
catch (e) { }
return 'validation error';
}
function queryFailed(error) {
var msg = 'Error retreiving data. ' + error.message;
logError(msg, error);
throw error;
}
function configureBreezeManager() {
breeze.NamingConvention.camelCase.setAsDefault();
var mgr = new breeze.EntityManager(config.remoteServiceName);
model.configureMetadataStore(mgr.metadataStore);
return mgr;
}
function getLookups() {
return EntityQuery.from('Lookups')
.using(manager).execute()
.then(processLookups)
.fail(queryFailed);
}
function processLookups() {
model.createNullos(manager);
}
function log(msg, data, showToast) {
logger.log(msg, data, system.getModuleId(datacontext), showToast);
}
function logError(msg, error) {
logger.logError(msg, error, system.getModuleId(datacontext), true);
}
//#endregion
});
Below is the code for BreezeController/WebApi
namespace CodeCamper.Controllers
{
[BreezeController]
public class BreezeController : ApiController
{
readonly EFContextProvider<CodeCamperDbContext> _contextProvider =
new EFContextProvider<CodeCamperDbContext>();
[HttpGet]
public string Metadata()
{
return _contextProvider.Metadata();
}
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _contextProvider.SaveChanges(saveBundle);
}
[HttpGet]
public object Lookups()
{
var rooms = _contextProvider.Context.Rooms;
var tracks = _contextProvider.Context.Tracks;
var timeslots = _contextProvider.Context.TimeSlots;
return new {rooms, tracks, timeslots};
}
[HttpGet]
public IQueryable<Session> Sessions()
{
return _contextProvider.Context.Sessions;
}
[HttpGet]
public IQueryable<Person> Persons()
{
return _contextProvider.Context.Persons;
}
[HttpGet]
public IQueryable<Person> Speakers()
{
return _contextProvider.Context.Persons
.Where(p => p.SpeakerSessions.Any());
}
}
}
Please help/advise.

returning different javascript object from controller

my controller action:
[HttpPost]
public ActionResult AddPointAndCopyOtherSongToPlaylist(int id)
{
if (CheckIfAddPointToSelf(User.Identity.Name, id))
{
var song = repository.GetSong(id);
foreach (var item in song.Points)
{
if (User.Identity.Name == item.UsernameGavePoint)
{
var data1 = 1;
return Json(new {data1}, JsonRequestBehavior.AllowGet);
}
}
var originalSong = repository.GetSong(id);
var newSong = new Song();
newSong.UserName = User.Identity.Name;
newSong.Title = originalSong.Title;
newSong.YoutubeLink = originalSong.YoutubeLink;
newSong.GenreId = 38;
newSong.Date = DateTime.Now;
repository.AddSong(newSong);
var point = new Point();
point.UsernameGotPoint = originalSong.UserName;
point.UsernameGavePoint = User.Identity.Name;
point.Date = DateTime.Now;
point.Score = 1;
point.OtherSongId = id;
repository.AddPoint(point);
repository.Save();
int data = 2;
//process here
return Json(new { data }, JsonRequestBehavior.AllowGet);
}
else
{
return null;
}
}
based on different scenarios I want to return a javascript and somehow notify the client of what was returned and based in the result do something in the success part of my ajax call:
$.ajax({
beforeSend: function () { ShowAjaxLoader(); },
url: "/Home/AddPointAndCopyOtherSongToPlaylist/",
type: "POST",
data: { id: songId },
success: function (data,one) {
if (data && !one) {
HideAjaxLoader(), ShowMsg("Song Added Successfully");
}
else if(!data) {
HideAjaxLoader(), ShowMsg("you cannot add your own songs");
}
else if (data && one) {
HideAjaxLoader(), ShowMsg("You cannot add the same song twice");
}
},
error: function () { HideAjaxLoader(), ShowMsg("Song could not be added, please try again") }
});
});
I tried many different variations but I think i need something like data.property1 returned and in the client to check if that property exists or soemthing like that.. please help
You need to return your status code within the object.
return Json( new { data1 = "Some Other Data", status = 1} );
Then in your success handler check data.status.
if (data.status === 1) {
alert(data.data1);
}

Resources