KendoUI MVVM validation using Datasource Model validation rules - kendo-ui

Just a little hack for validating against a kendo.data.Model
So instead of adding the HTML5 required attribute to each input field manually
this little hack gets all the validation rules that you defined in your Model and
add them as attributes to the appropriate field. Not fully tested just a quick hack. According to Kendo the validation rules don't get processed if you are using MVVM, but they do if for example you bind the Dataource directly to a grid.
Code:
I just put this code in a file called definevalidation.js
function getValidationAttributesFromModel(myFields) {
var myValidatedFields = [];
var obj = null;
$.each(myFields, function(fieldName) {
if (this.validation) {
var obj = {
fieldName : fieldName,
validation : this.validation
};
myValidatedFields.push(obj);
}
});
addValidationAttributes(myValidatedFields);
}
function addValidationAttributes(myValidatedFields) {
$.each(myValidatedFields, function(index) {
$('#' + this.fieldName).attr(this.validation);
});
}
Usage:
If ParentDS is your datasource then in your form code just use
getValidationAttributesFromModel(ParentDS.options.schema.model.fields)
Sample Model:
mydatamodel = kendo.data.Model.define({
id : "__KEY",
fields : {
__KEY : {
type : "string"
},
__STAMP : {
type : "number"
},
ID : {
editable : false,
nullable : true
},
firstName : {
type : "string",
validation : {
required : true
}
},
middleName : {
type : "string"
},
lastName : {
type : "string"
}
}
});

Related

How to read GraphQL enum values in AppSync resolver template?

I have an enum in my schema in the following way:
type Item {
name: String!
}
enum ItemType {
Simple
Advanced
}
input ValueSimple { simple: Int }
input ValueAdvanced { advanced: Int }
input InputItemSchedule {
type: ItemType!
valueSimple: ValueSimple
valueAdvanced: ValueAdvanced
}
mutation Mutation {
addItem(name: String!, schedule: [InputItemSchedule]!): Item
}
I am trying to do conditional checks in the AppSync resolver template (data source id DynamoDB) but I don't know how to get the value for the item type:
#set($schedule = {})
#foreach($item in $context.args.schedule)
#set($scheduleItem = { })
#if($item.type == "Simple")
#set($scheduleItem.value = $item.valueSimple)
#elseif($item.type == "Advanced")
#set($scheduleItem.value = $item.valueAdvanced)
#else
## Set the type value to value for testing purposes
#set($scheduleItem.value = $util.dynamodb.toDynamoDBJson($item.type))
#end
$util.qr($schedule.add($scheduleItem))
#end
{
"version" : "2017-02-28",
"operation" : "PutItem",
"key" : {
"id": $util.dynamodb.toDynamoDBJson($util.autoId()),
},
"attributeValues" : {
"name": $util.dynamodb.toDynamoDBJson($ctx.args.name),
"schedule": $util.dynamodb.toDynamoDBJson($schedule)
}
}
When I make a request that triggers the resolver regardless of the enum value, I keep getting the following in DynamoDB:
...
"value": {
"S": "null"
}
How am I supposed to read the GraphQL enum value from the resolver template?

Kendo grid Use previous filter values on relaod dosn't work

I'm trying to keep the filter value into KendoGrid and reuse it on relaod.
I find some code sample but doesn't working. I used getOptions to store values into localStorage. It's working. I have values into localStorage["kendo-grid-options"]. On reload, value appears into filters on header grid but data don't load. Error in the consoel is :
[! - SessionID: q0pbq0zsol3mjsxtd5mlendu, PageInstanceID: d11a8e2e-d716-43a0-8f4e-679eb87ad167, DateTime: 04/20/2022 20:53:10.894] Message: Uncaught
TypeError: Cannot read properties of undefined (reading 'data')
Impossible to find solution. If somebody has en idea... :)
My code is the following
function LoadSampleQualityControlPlanGridSummary(control,params) {
control.dataSource = new kendo.data.DataSource({ transport: {
read: function (options) {
GetDsBySp("sp_HMI_GetSampleControlPlanList", params, options.success);} }, schema: { model: {
id: "qm_spec_id" }, fields: {
qm_spec_desc: {
type: "string"
},
plan_name: {
type: "string"
} } } }); }
function InitSampleQualityControlPlanSummaryGrid(control) {
control.columns = [ { field: "qm_spec_name", title:
"Name") }, { field: "qm_spec_desc", title: "description")
}, { field: "plan_name", title: "Plan", } ]; }
//On load
_controls.SampleControlPlanSummary = control.findByXmlNode("GSQCP");
_controls.$SampleControlPlanSummary = $(_controls.SampleControlPlanSummary.domElement).data("kendoGrid");
InitSampleQualityControlPlanSummaryGrid(_controls.SampleControlPlanSummary);
var options = localStorage["kendo-grid-options"];
if (options) {
var parsedOptions = JSON.parse(options);
_controls.$SampleControlPlanSummary.setOptions(parsedOptions); _controls.$SampleControlPlanSummary.setDataSource(gridData);
} LoadSampleQualityControlPlanGridSummary(_controls.SampleControlPlanSummary,
paramControl);

SAPUI5/OpenUI5 view not rendered after router navTo

I'm creating SAPUI5 sample app with simple routing (SAPUI5/OpenUI5 v.1.22).
My main problem, which I'm trying to understand, why URL pattern changes and the onInit of target view controller is fired, but after nothing happens (onAfterRendering not fired), and I'm able to go to another page only after page reload.
Routing setup. Compontent.js, where router is initialized, is structured in following way:
sap.ui.define([
"sap/ui/core/UIComponent"
], function (UIComponent) {
return UIComponent.extend("sge.apps.app.Component", {
metadata:{
name : "Sample App",
version : "1.0",
includes : [],
dependencies : {
libs : ["sap.m", "sap.ui.layout"],
components : []
},
rootView: "sge.apps.app.view.App",
config: {
resourceBundle: "i18n/i18n.properties"
},
routing : {
config : {
routerClass : sap.ui.core.routing.Router,
viewType : "XML",
viewPath : "sge.apps.app.view",
targetControl: "app",
targetAggregation: "pages",
transition: "slide",
clearTarget : false,
bypassed: {
target: "notFound"
}
},
routes: [{
pattern: "",
name: "appHome",
view: "Home"
},{
pattern : ":all*:",
name : "catchallDetail",
view : "NotFound",
transition : "show"
},{
pattern: "notFound",
name: "appNotFound",
view: "NotFound",
transition : "show"
}]
}
},
init : function() {
UIComponent.prototype.init.apply(this, arguments);
var mConfig = this.getMetadata().getConfig();
// always use absolute paths relative to our own component
// (relative paths will fail if running in the Fiori Launchpad)
var rootPath = jQuery.sap.getModulePath("sge.apps.app");
// set i18n model
var i18nModel = new sap.ui.model.resource.ResourceModel({
bundleUrl : [rootPath, mConfig.resourceBundle].join("/")
});
this.setModel(i18nModel, "i18n");
// set device model
var deviceModel = new sap.ui.model.json.JSONModel({
isTouch : sap.ui.Device.support.touch,
isNoTouch : !sap.ui.Device.support.touch,
isPhone : sap.ui.Device.system.phone,
isNoPhone : !sap.ui.Device.system.phone,
listMode : sap.ui.Device.system.phone ? "None" : "SingleSelectMaster",
listItemType : sap.ui.Device.system.phone ? "Active" : "Inactive"
});
deviceModel.setDefaultBindingMode("OneWay");
this.setModel(deviceModel, "device");
this.getRouter().initialize();
}
});
});
I have Home.controller.js of the Home.view.xml from where I try to navigate to another view, by pressing the button with event onDisplayNotFound:
sap.ui.define([
"sge/apps/app/controller/BaseController"
], function (BaseController) {
"use strict";
return BaseController.extend("sge.apps.app.controller.Home", {
onDisplayNotFound : function (oEvent) {
this.getRouter().navTo("appNotFound");
}
});
});
BaseController.js
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/core/routing/History"
], function (Controller, History) {
"use strict";
return Controller.extend("sge.apps.app.controller.BaseController", {
getRouter: function () {
return sap.ui.core.UIComponent.getRouterFor(this);
},
onNavBack: function (oEvent) {
var oHistory, sPreviousHash;
oHistory = History.getInstance();
sPreviousHash = oHistory.getPreviousHash();
if(sPreviousHash !== undefined) {
window.history.go(-1);
} else {
this.getRouter().navTo("appHome", {}, true /*no history*/);
}
}
});
});
NotFound.controller.js of target view NotFound.view.xml:
sap.ui.define([
"sge/apps/app/controller/BaseController"
], function (BaseController) {
"use strict";
return BaseController.extend("sge.apps.app.controller.NotFound", {
onInit: function () {
console.log("onInit NotFound.view.xml");
},
onAfterRendering: function () {
console.log("onAfterRendering NotFound.view.xml");
}
});
});
I had the same problem and I solved by adding this line in the configuration of the routing :
"routerClass" : "sap.m.routing.Router",
And it has worked perfectly navigation.
"routing": {
"config": {
"routerClass" : "sap.m.routing.Router",
"viewPath": "es.seidor.view",
"controlId": "App",
"async" : "true",
"clearTarget" : "true"
}
sap.ui.define is a feature of UI5 v1.30
Either update the version you're using to 1.30.x or remove the sap.ui.define code and replace it with code that works with the earlier versions.
Pre-sap.ui.define code looks something like this:
jQuery.sap.require("sap.m.Button");
//use jQuery.sap.require to require any controls or other files
sap.ui.controller("my.controller", {
onInit: function(){
//your code here
//doing something with sap.m.Button, won't work without the require
//var oBtn = new sap.m.Button("myBtn", {text: "Click me"});
},
onAfterRendering: function(){
//more code
}
});
Try that.
The solution is simple, just use some part of TDG best practice:
Create the file MyRouter.js
sap.ui.define([
"sap/ui/core/routing/Router",
"sap/m/routing/RouteMatchedHandler"
], function (Router, RouteMatchedHandler) {
"use strict";
return Router.extend("sge.apps.notespese.MyRouter", {
constructor : function() {
sap.ui.core.routing.Router.apply(this, arguments);
this._oRouteMatchedHandler = new sap.m.routing.RouteMatchedHandler(this);
},
destroy : function() {
sap.ui.core.routing.Router.prototype.destroy.apply(this, arguments);
this._oRouteMatchedHandler.destroy();
}
});
});
Inject it in your Component.js, as follows:
sap.ui.define([
"sap/ui/core/UIComponent",
"sge/apps/notespese/MyRouter"
], function (UIComponent, MyRouter) {
"use strict";
return UIComponent.extend("sge.apps.notespese.Component", {
...
In Component metadata section replace
routing : {
config : {
routerClass : sap.ui.core.routing.Router,
with
routing : {
config : {
routerClass : sge.apps.notespese.MyRouter,
Hope to do not forget other this question related things.

How to validate sap.m.DatePicker selection against a dynamic minimum date?

Normal way to validate sap.m.DatePicker input looks like this:
new sap.m.DatePicker({
value : {
path : "someModel>/SomeDate",
type : new sap.ui.model.type.Date({}, {
minimum : new Date()
})
}
})
I have the problem, that the "minimum" date will depend on different other parameters.
Binding in a type seems not working (or I do something wrong?).
I would be happy to have a function like this:
new sap.m.DatePicker({
value : {
path : "someModel>/SomeDate",
type : new sap.ui.model.type.Date({}, {
minimum : "{someModel>/MinimumDate}"
})
}
})
Anyone an idea how to solve this?
I prefer to avoid the usage of id's to grab for a control in the controller.
I build the following solution. Maybe there is a better way?
Definition of data type:
jQuery.sap.declare("my.CallbackDateType");
sap.ui.model.type.Date.extend("my.CallbackDateType", {
constructor : function () {
sap.ui.model.type.Date.apply(this, arguments);
this.sName = "CallbackDateType";
},
validateValue : function(oValue) {
var that = this;
if (that.oConstraints.callback!==undefined) {
that.oConstraints.callback[0].call(that.oConstraints.callback[1], that);
}
return sap.ui.model.type.Date.prototype.validateValue.call(this, oValue);
}
});
Use like this:
new sap.m.DatePicker({
value : {
path : "model>/Date",
type : new my.CallbackDateType({}, {
minimum : new Date(),
callback : [oController.getMinimumDate, oController]
})
}
})

sequelize validation method

I'm trying to validate my Model but i miss something and i don't know what is it.
It is my module and his validation for email.
module.exports = function(sequelize, DataTypes){
return sequelize.define("Scanner",
{
id : {
primaryKey : true,
autoIncrement : true,
type : DataTypes.INTEGER
},
email : {
type : DataTypes.STRING,
isUnique :true,
allowNull:false,
validate:{
isEmail : true
}
},
pin : {
type : DataTypes.INTEGER
}
},{
tableName : 'scanner'
});
};
When i'm trying to Find an object with parameters (pin + email) if i put this.email = ssdf.sdf , my query is launched and i would like to check first if my params are correct.
Scanner.prototype.getScannerByCredentials = function(callback){
//Send only Field id and email
_Scanner.find({ where: { email : this.email, pin :this.pin},attributes:['id','email'] }).success(function(scanner) {
return callback(null, scanner);
}).error(function(error){
console.log(error);
return callback(error, null);
});
};
I tried with validate() method but i've got as error : Object [object Object] has no method 'validate' and when i'm made a console.log(_Scanner); i saw my function validate() so i don't know why that's doesn't work..
Scanner.prototype.getScannerByCredentials = function(callback){
//Send only Field id and email
_Scanner.find({ where: { email : this.email, pin :this.pin},attributes:['id','email'] }).validate().success(function(scanner) {
return callback(null, scanner);
}).error(function(error){
console.log(error);
return callback(error, null);
});
};
I'm reading the docs and try a lot of thing founded on the net so if someone could explain to me what's wrong, it will be really nice.
Thanks a lot in advance.
EDIT : FOUND !
My solution if you're interested :)
My Models :
module.exports = function(sequelize, DataTypes){
return sequelize.define("Scanner",
{
id : {
primaryKey : true,
autoIncrement : true,
type : DataTypes.INTEGER,
allowNull : false
},
email : {
type : DataTypes.STRING,
isUnique :true,
allowNull:false,
validate:{
isEmail : true
}
},
pin : {
type : DataTypes.INTEGER
}
},{
tableName : 'scanner',
classMethods:{
isValid : function(objScanner) {
return this.build(objScanner).validate() ? true : false ;
}
}
});
};
My credentials Method :
Scanner.prototype.getScannerByCredentials = function(callback){
//MODIF THIS PART / NEED TO IMPROVE
var error = _Scanner.build({ email : this.email, pin : this.pin}).validate();
if(error === null){
_Scanner.find({ where: { email : this.email, pin :this.pin},attributes:['id','email'] }).success(function(scanner) {
console.log(scanner);
return callback(null, scanner);
}).error(function(error){
console.log(error);
return callback(error, null);
});
}
else
return callback(error,null);
};
And my generic update method (bonus) :
Scanner.prototype.update= function(callback){
var self = this;
_Scanner.find(this.id).success(function(scannerFound){
if(scannerFound){
//Set old Values by New Values : only values changed
scannerFound.dataValues = ormize(self,scannerFound.dataValues);
//Check validation Fields before insert DB
if(_Scanner.isValid(scannerFound)){
scannerFound.save().success(function(){
return callback(true);
}).error(function(error){
return callback(false);
});
}else
return callback(false);
}else
return callback(false);
}).error(function(error){
console.log(error);
return callback(false);
});
};
If you have any advice with my code it will be grateful too :)
Thank a lot in advance
What version do you use? This should have been fixed
The field should look like this.
isEmail: {msg: 'Reason'}

Resources