Extjs validate in separate files - validation

I'm trying to validate fields in my form, but I keep getting an error message.
Here is my code:
Ext.define('ExtDoc.views.extfields.FieldsValidator',{
valEng: function(val) {
var engTest = /^[a-zA-Z0-9\s]+$/;
Ext.apply(Ext.form.field.VTypes, {
eng: function(val, field) {
return engTest.test(val);
},
engText: 'Write it in English Please',
// vtype Mask property: The keystroke filter mask
engMask: /[a-zA-Z0-9_\u0600-\u06FF\s]/i
});
}
});
And I define my field as follow:
{
"name": "tik_moed_chasifa",
"type": "ExtDoc.views.extfields.ExtDocTextField",
"label": "moed_hasifa",
"vtype": "eng",
"msgTarget": "under"
}
The first snippet is in a separate js file, and I have it in my fields js file as required.
When I start typing text in the text field, I keep seeing the following error msg in the explorer debugger:
"SCRIPT438: Object doesn't support property or method 'eng' "
What could it be? Have I declared something wrong?

You have defined your own class with a function valEng(val), but you don't instantiate it, neither do you call the function anywhere.
Furthermore, your function valEng(val) does not require a parameter, because you are not using that parameter anywhere.
It would be far easier and more readable, would you remove the Ext.define part and create the validators right where you need them. For instance if you need them inside an initComponent function:
initComponent:function() {
var me = this;
Ext.apply(Ext.form.field.VTypes, {
mobileNumber:function(val, field) {
var numeric = /^[0-9]+$/
if(!Ext.String.startsWith(val,'+')) return false;
if(!numeric.test(val.substring(1))) return false;
return true;
},
mobileNumberText:'This is not a valid mobile number'
});
Ext.apply(me,{
....
items: [{
xtype:'fieldcontainer',
items:[{
xtype: 'combobox',
vtype: 'mobileNumber',
Or, you could add to your Application.js, in the init method, if you need it quite often at different levels of your application:
Ext.define('MyApp.Application', {
extend: 'Ext.app.Application',
views: [
],
controllers: [
],
stores: [
],
init:function() {
Ext.apply(Ext.form.field.VTypes, {
mobileNumber:function(val, field) {
var numeric = /^[0-9]+$/
if(!Ext.String.startsWith(val,'+')) return false;
if(!numeric.test(val.substring(1))) return false;
return true;
},
mobileNumberText:'This is not a valid mobile number'
});
}

Related

How to modify just a property from a dexie store without deleting the rest?

I'm having the dexie stores showed in the print screen below:
Dexie stores print screen
My goal is to update a dexie field row from a store without losing the rest of the data.
For example: when I edit and save the field "com_name" from the second row (key={2}) I want to update "com_name" only and not lose the rest of the properties, see first and the third row.
I already tried with collection.modify and table.update but both deleted the rest of the properties when used the code below:
dexieDB.table('company').where('dexieKey').equals('{1}')
//USING table.update
//.update(dexieRecord.dexiekey, {
// company: {
// com_name: "TOP SERVE 2"
// }
//})
.modify(
{
company:
{
com_name: TOP SERVE 2
}
}
)
.then(function (updated) {
if (updated)
console.log("Success.");
else
console.log("Nothing was updated.");
})
.catch(function (err) { console.log(err); });
Any idea how can I accomplish that?
Thanks
Alex
You where right to use Table.update or Collection.modify. They should never delete other properties than the ones specified. Can you paste a jsitor.com or jsfiddle repro of that and someone may help you pinpoint why the code doesn't work as expected.
Now that you are saying I realised that company and contact stores are created dynamically and editedRecords store has the indexes explicitly declared therefore when update company or contact store, since dexie doesn't see the indexes will overwrite. I haven't tested it yet but I suspect this is the behaviour.
See the print screen below:
Dexie stores overview
Basically I have json raw data from db and in the browser I create the stores and stores data based on it, see code below:
function createDexieTables(jsonData) { //jsonData - array, is the json from db
const stores = {};
const editedRecordsTable = 'editedRecords';
jsonData.forEach((jsonPackage) => {
for (table in jsonPackage) {
if (_.find(dexieDB.tables, { 'name': table }) == undefined) {
stores[table] = 'dexieKey';
}
}
});
stores[editedRecordsTable] = 'dexieKey, table';
addDataToDexie(stores, jsonData);
}
function addDataToDexie(stores, jsonData) {
dbv1 = dexieDB.version(1);
if (jsonData.length > 0) {
dbv1.stores(stores);
jsonData.forEach((jsonPackage) => {
for (table in jsonPackage) {
jsonPackage[table].forEach((tableRow) => {
dexieDB.table(table).add(tableRow)
.then(function () {
console.log(tableRow, ' added to dexie db.');
})
.catch(function () {
console.log(tableRow, ' already exists.');
});
});
}
});
}
}
This is the json, which I convert to object and save to dexie in the value column and the key si "dexieKey":
[
{
"company": [
{
"dexieKey": "{1}",
"company": {
"com_pk": 1,
"com_name": "CloudFire",
"com_city": "Round Rock",
"serverLastEdit": [
{
"com_pk": "2021-06-02T11:30:24.774Z"
},
{
"com_name": "2021-06-02T11:30:24.774Z"
},
{
"com_city": "2021-06-02T11:30:24.774Z"
}
],
"userLastEdit": []
}
}
]
}
]
Any idea why indexes were not populated when generating them dynamically?
Given the JSON data, i understand what's going wrong.
Instead of passing the following to update():
{
company:
{
com_name: "TOP SERVE 2"
}
}
You probably meant to pass this:
{
"company.com_name": "TOP SERVE 2"
}
Another hint is to do the add within an rw transaction, or even better if you can use bulkAdd() instead to optimize the performance.

What happens if you do a get item in DynamoDb using a projection expression, if the attribute in the expression may not exist

Inside a lambda, I'm calling getItem on a a table with a projection expression for a single field. This is working fine.
const usersTableParams = {
TableName: 'users',
Key: {
'user-name': { S: userID }
},
ProjectionExpression: 'notificationEndpointARN'
};
ddb.getItem(usersTableParams, function (err, data) {
if (err) {
console.log('error getting user info', err);
}
else {
// success
// code...
}
});
Now I want to add another attribute to the projection expression, but that attribute might not exist yet on the item. (If it doesn't exist I will add it at the end of the function).
Does the function fail, does it return null for that attribute, does it not return that attribute at all?
I can't find the answer in the documentation or in any google searches.
If Projection-Expression contains an attribute that doesn't exist in the table, it doesn't throw any error or return null.
It will simply not appear in the result and return the remaining found attributes .
cli> aws dynamodb get-item --table-name my-DynamoDBTable-I3BL7EX05JQR --key file://test.json --projection-expression "data_type,ts,username"
{
"Item": {
"ts": {
"N": "1600755209826"
},
"data_type": {
"S": "Int32"
}
}
}
You can refer this for details: https://docs.aws.amazon.com/cli/latest/reference/dynamodb/get-item.html

In FormFlow, How do i get the form values after form is done?

I have a complete Form that has different fields. Name, phone and so on.
Before complition, I would like to send the fields to a method then then sends an email. More specificly, I want to put the values on a dictionary and then pass it to the method.
Where are those values stored in the Form so I can get them?
This is my code
form.OnCompletion(processOrder);
var parameters = new Dictionary<string, string>
{
{ "tileid", "open" },
{ "src", "Facebook" },
{ "chid", "9" },
{ "apply-first-name", "xxx" },
{ "apply-last-name", "xxx" },
{ "apply-email", "xxx" }
};
sendAsync(parameters);
return form.Build();
I found the answer. All values are inside the ”state” objekt passed to the oncompletion method.

JqGrid custom formatter with custom parameter

I have a question about custom formatters.
What I try to achieve is a currencyFormatter just for the amount with Locale sent by the server, when locale is not define or supported fall back to British English.
Something like this:
function currencyFmatter(cellvalue, options, rowdata) {
return new Intl.NumberFormat([locale, "en-GB"], {minimumFractionDigits: 2, maximumFractionDigits: 2}).format(cellvalue);
}
My problem is how to pass my variable locale to the formatter, I’m pretty sure it has to be a way to do it but right now I don’t see it.
Thanks
It's an interesting question! There are many ways to implement your requirements.
1) you can extend your input data returned from the server with additional information which specify the locale of data. For example you can returns "de-DE:10.000,04" instead of "10.000,04" which represent 1000.04 formatted in German locale (where , will be used as the decimal separator and . used as the thousands separator). It allows you to use cellvalue.split(":") to get array ["de-DE", "10.000,04"] with the locale of the number and the number itself
function currencyFmatter(cellvalue, options, rowdata) {
var data;
if (typeof cellvalue === "string") {
data = cellvalue.cellvalue.split(":");
if (data.length === 2) {
return new Intl.NumberFormat([data[0], "en-GB"], {
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(data[1]);
}
}
return cellvalue;
}
Alternatively you can place the information about locale of the number in separate field (for example numLocale) of the input data and use something like rowdata.numLocale (or rowdata[12] depend on the input format of the JSON data) to access the locale.
2) It could be that all the data returned from the server will be in the same format. In the case it would be not the best way to prepend all numbers with the same prefix "de-DE:". What you can do for example is to extend the data returned from the server with additional field. For example you can use
{
"total": "12",
"page": "1",
"records": "12345",
"localOfNumbers": "de-DE",
"rows" : [
...
]
}
You can access the custom localOfNumbers field inside of beforeProcessing callback. It's very practical callback. It allows you to pre-process the data returned from the server before the data will be processed by jqGrid. I recommend you to read the answer and this one for more code example. What you can do for example is to save localOfNumbers value in some new option of jqGrid (see the answer for more details). Let us you want to have an option gridLocale for the goal. Then you can do something like the following:
beforeProcessing: function (data) {
if (typeof data.localOfNumbers === "string") {
$(this).jqGrid("setGridParam", {gridLocale: data.localOfNumbers});
}
}
To access the new gridLocale option you can use
function currencyFmatter(cellvalue, options, rowdata) {
var locale = $(this).jqGrid("getGridParam", "gridLocale"); // this.p.gridLocale
}
3) You can consider to save the information about the locale as column property instead of usage one common gridLocale grid option. To do this you can define the column in colModel like below
{ name: 'col2', width: 200, formatoptions: { colLocale: "en-IN" },
formatter: function (cellvalue, options, rowdata) {
// options.colModel.formatoptions.colLocale get you the value
}
One can set the property of formatoptions.colLocale inside of beforeProcessing too. You can use
{
"total": "12",
"page": "1",
"records": "12345",
"localOfColumns": {
"col2": "de-DE",
"col5": "en-IN"
},
"rows" : [
...
]
}
and
beforeProcessing: function (data) {
if ($.isPlainObject(data.localOfColumns)) {
if (typeof data.localOfColumns.col2 === "string") {
$(this).jqGrid("setColProp", "col2", {
formatoptions: { colLocale: data.localOfColumns.col2 }
});
}
if (typeof data.localOfColumns.col5 === "string") {
$(this).jqGrid("setColProp", "col5", {
formatoptions: { colLocale: data.localOfColumns.col5 }
});
}
}
}
I'm sure that one can suggest even more ways to implement your requirements.

Translating JSON into custom dijit objects

I am looking for an example where JSON constructed from the server side is used to represent objects that are then translated into customized widgets in dojo. The JSON would have to be very specific in its structure, so it would not be a very general solution. Could someone point me to an example of this. It would essentially be the reverse of this
http://docs.dojocampus.org/dojo/formToJson
First of all let me point out that JSON produced by dojo.formToJson() is not enough to recreate the original widgets:
{"field1": "value1", "field2": "value2"}
field1 can be literally anything: a checkbox, a radio button, a select, a text area, a text box, or anything else. You have to be more specific what widgets to use to represent fields. And I am not even touching the whole UI presentation layer: placement, styling, and so on.
But it is possible to a certain degree.
If we want to use Dojo widgets (Dijits), we can leverage the fact that they all are created uniformly:
var myDijit = new dijit.form.DijitName(props, node);
In this line:
dijit.form.DijitName is a dijit's class.
props is a dijit-specific properties.
node is an anchor node where to place this dijit. It is optional, and you don't need to specify it, but at some point you have to insert your dijit manually.
So let's encode this information as a JSON string taking this dijit snippet as an example:
var myDijit = new dijit.form.DropDownSelect({
options: [
{ label: 'foo', value: 'foo', selected: true },
{ label: 'bar', value: 'bar' }
]
}, "myNode");
The corresponding JSON can be something like that:
{
type: "DropDownSelect",
props: {
options: [
{ label: 'foo', value: 'foo', selected: true },
{ label: 'bar', value: 'bar' }
]
},
node: "myNode"
}
And the code to parse it:
function createDijit(json){
if(!json.type){
throw new Error("type is missing!");
}
var cls = dojo.getObject(json.type, false, dijit.form);
if(!cls){
// we couldn't find the type in dijit.form
// dojox widget? custom widget? let's try the global scope
cls = dojo.getObject(json.type, false);
}
if(!cls){
throw new Error("cannot find your widget type!");
}
var myDijit = new cls(json.props, json.node);
return myDijit;
}
That's it. This snippet correctly handles the dot notation in types, and it is smart enough to check the global scope too, so you can use JSON like that for your custom dijits:
{
type: "my.form.Box",
props: {
label: "The answer is:",
value: 42
},
node: "answer"
}
You can treat DOM elements the same way by wrapping dojo.create() function, which unifies the creation of DOM elements:
var myWidget = dojo.create("input", {
type: "text",
value: "42"
}, "myNode", "replace");
Obviously you can specify any placement option, or no placement at all.
Now let's repeat the familiar procedure and create our JSON sample:
{
tag: "input",
props: {
type: "text",
value: 42
},
node: "myNode",
pos: "replace"
}
And the code to parse it is straightforward:
function createNode(json){
if(!json.tag){
throw new Error("tag is missing!");
}
var myNode = dojo.create(json.tag, json.props, json.node, json.pos);
return myNode;
}
You can even categorize JSON items dynamically:
function create(json){
if("tag" in json){
// this is a node definition
return createNode(json);
}
// otherwise it is a dijit definition
return createDijit(json);
}
You can represent your form as an array of JSON snippets we defined earlier and go over it creating your widgets:
function createForm(array){
dojo.forEach(array, create);
}
All functions are trivial and essentially one-liners — just how I like it ;-)
I hope it'll give you something to build on your own custom solution.

Resources