how to set validation in angular formly - angular-formly

i am creating a form using formly there are two input text box and i want that both the text box should not be empty.How to set validation
my code is:
form: FormGroup = new FormGroup({});
userFields: FormlyFieldConfig = [{
className: 'row',
fieldGroup: [{
className: 'col-xs-6',
key: 'identity',
type: 'input',
templateOptions: {
validate: true,
required: true,
type: 'email',
label: 'Email address',
placeholder: 'Enter email',
}
}, {
className: 'col-xs-6',
key: 'password',
type: 'input',
templateOptions: {
validate: true,
required: true,
type: 'password',
label: 'Password',
placeholder: 'Password',
validationsCustom: 'validation.html'
}
}]
}];

You should include FormlyModule with some configuration to your AppModule. In your case, you should include error name required and message 'This field is required.'
For example:
import { FormlyModule } from '#ngx-formly/core';
#NgModule({
imports: [
FormlyModule.forRoot({
validationMessages: [
{ name: 'required', message: 'This field is required.' },
],
}),
],
})
export class AppModule {}
More information related to validation you can see there https://formly.dev/guide/validation

Related

"dataValues" is not allowed by JOI.validate()

Here is code for User model with JOI (14.3) validation. The code used to be working when creating new user but it seems got flu recently and throws out error of xxx not allowed:
require('dotenv').config({path: process.cwd() +'\\config\\.env'});
const jwt = require('jsonwebtoken');
const moment = require('moment');
const Joi = require('joi');
const Sql = require('sequelize');
const db = require("../startup/db");
const User = db.define('user', {
name: {type: Sql.STRING,
allowNull: false,
min: 2,
max: 50,
},
email: {type: Sql.STRING,
isEmail: true
},
cell: {type: Sql.STRING,
allowNull: false,
min: 10,
max: 20,
},
cell_country_code: {type: Sql.STRING,
allowNull: false
},
comp_name: {type: Sql.STRING
},
status: {type: Sql.STRING,
allowNull: false,
isIn: ['active', 'blocked', 'inactive', 'pending', 'unverified']
},
role: {type: Sql.STRING,
allowNull: false
},
device_id: {type: Sql.STRING, //maybe empty when the user is initially created.
},
user_data: {type: Sql.JSONB
},
last_updated_by_id: {type: Sql.INTEGER},
fort_token: {type: Sql.STRING,
allowNull: false,
min: 20 //64 for production
},
createdAt: Sql.DATE,
updatedAt: Sql.DATE
}, {
indexes: [
{
//For same fort_token, name to be unique
unique: true,
fields: ['name', 'fort_token']
}, {
//unique cell
//unique: true,
fields: ['cell_country_code', 'cell', 'status']
}, {
fields: ['cell_country_code', 'cell']
}, {
//email
fields: ['email']
}, {
fields: ['device_id']
}, {
fields: ['status']
}, {
fields: ['fort_token']
}
]
});
function validateUser(user) {
const schema = {
name: Joi.string()
.min(2)
.max(50)
.required()
.trim(),
cell: Joi.string()
.min(10)
.max(20)
.trim()
.required()
.error(new Error('该手机号有误!')),
cell_country_code: Joi.string()
.trim()
.required(),
role: Joi.string()
.required()
.trim(),
email: Joi.string()
.email()
.allow("")
.optional()
};
return Joi.validate(user, schema);
};
Here is the error:
new user data : { _device_id: '8c9c25711c7d0262',
cell: '8008006414 ',
cell_country_code: '1',
name: 'ss9',
corp_name: '',
role: 'eventer',
email: '',
user_data: { avatar: '' } }
error in user validate : { ValidationError: "dataValues" is not allowed. "_previousDataValues" is not allowed. "_changed" is not allowed. "_modelOptions" is not allowed. "_options" is not allowed. "isNewRecord" is not allowed
at Object.exports.process (C:\d\code\js\emps_bbone\node_modules\joi\lib\errors.js:203:19)
at internals.Object._validateWithOptions (C:\d\code\js\emps_bbone\node_modules\joi\lib\types\any\index.js:764:31)
at module.exports.internals.Any.root.validate (C:\d\code\js\emps_bbone\node_modules\joi\lib\index.js:147:23)
at validateUser (C:\d\code\js\emps_bbone\models\user.js:106:16)
at router.post (C:\d\code\js\emps_bbone\routes\users.js:217:27)
at newFn (C:\d\code\js\emps_bbone\node_modules\express-async-errors\index.js:16:20)
at Layer.handle [as handle_request] (C:\d\code\js\emps_bbone\node_modules\express\lib\router\layer.js:95:5)
at next (C:\d\code\js\emps_bbone\node_modules\express\lib\router\route.js:137:13)
at C:\d\code\js\emps_bbone\middleware\auth_role.js:7:7
at newFn (C:\d\code\js\emps_bbone\node_modules\express-async-errors\index.js:16:20)
at Layer.handle [as handle_request] (C:\d\code\js\emps_bbone\node_modules\express\lib\router\layer.js:95:5)
at next (C:\d\code\js\emps_bbone\node_modules\express\lib\router\route.js:137:13)
at module.exports (C:\d\code\js\emps_bbone\middleware\auth_userinfo.js:106:13)
isJoi: true,
name: 'ValidationError',
details:
[ { message: '"dataValues" is not allowed',
path: [Array],
type: 'object.allowUnknown',
context: [Object] },
{ message: '"_previousDataValues" is not allowed',
path: [Array],
type: 'object.allowUnknown',
context: [Object] },
{ message: '"_changed" is not allowed',
path: [Array],
type: 'object.allowUnknown',
context: [Object] },
{ message: '"_modelOptions" is not allowed',
path: [Array],
type: 'object.allowUnknown',
context: [Object] },
{ message: '"_options" is not allowed',
path: [Array],
type: 'object.allowUnknown',
context: [Object] },
{ message: '"isNewRecord" is not allowed',
path: [Array],
type: 'object.allowUnknown',
context: [Object] } ],
_object:
user {
dataValues:
{ id: null,
name: 'ss9',
cell: '8008006414',
cell_country_code: '1',
email: '',
role: 'eventer' },
_previousDataValues:
{ name: undefined,
cell: '8008006414 ',
cell_country_code: undefined,
email: undefined,
role: undefined },
_changed:
{ name: true,
cell: true,
cell_country_code: true,
email: true,
role: true },
_modelOptions:
{ timestamps: true,
validate: {},
freezeTableName: false,
underscored: false,
paranoid: false,
rejectOnEmpty: false,
whereCollection: [Object],
schema: null,
schemaDelimiter: '',
defaultScope: {},
scopes: {},
indexes: [Array],
name: [Object],
omitNull: false,
sequelize: [Sequelize],
hooks: {} },
_options: { isNewRecord: true, _schema: null, _schemaDelimiter: '' },
isNewRecord: true },
annotate: [Function] }
error in new user
Here is the code for creating new user:
try {
user = new User(_.pick(req.body, ["name", "cell", "cell_country_code", "email", "role" ]));
const { error } = validateUser(user); //<<====== throws error with JOI.validate()
console.log("error in user validate : ", error);
if (error) {console.log("error in new user "); return res.status(400).send(error.details[0].message)};
I have no clue what the validation error is about.
You need to pass option with "allowUnknown:true" as the third argument of validate function
https://github.com/hapijs/joi/blob/v15.0.3/API.md#validatevalue-schema-options-callback

Slack Dialog.open not Opening if Variable is in Title

Whenever I try to add a variable to my dialog title, dialog.open does not work and no errors are thrown.
If I remove the variable from the title everything works fine, it is only when I add the variable to the title
I execute this before I define dialog
app.post('/create', function(req, res) {
var users = []
var {
text, trigger_id
} = req.body;
text = text.toUpperCase()
var issuetypes = []
axios({
method: 'get',
url: baseURL + 'project/' + text
}).then(function(response) {
for (var i = 0; i < response.data.issueTypes.length; i++) {
issuetypes.push({
label: response.data.issueTypes[i].name,
value: response.data.issueTypes[i].name
});
}
Does not work:
const dialog = {
token: botToken,
trigger_id,
dialog: JSON.stringify({
title: 'Create a new ' + text + ' Ticket',
callback_id: 'submit-ticket',
submit_label: 'Submit',
elements: [{
label: 'Project',
type: 'text',
name: 'project'
}, {
label: 'Summary',
type: 'text',
name: 'summary',
}, {
label: 'Description',
type: 'textarea',
name: 'description',
optional: true,
}, {
label: 'Type',
type: 'select',
name: 'type',
options: issuetypes,
}, {
label: 'Reporter',
type: 'select',
name: 'reporter',
optional: true,
options: [{
label: 'Reporter',
value: 'reporter'
}, ],
}, {
label: 'Link',
type: 'select',
name: 'epic',
optional: true,
options: [{
label: 'Epic',
value: 'epic'
}, ],
}, ],
}),
};
Works:
const dialog = {
token: botToken,
trigger_id,
dialog: JSON.stringify({
title: 'Create a new Ticket',
callback_id: 'submit-ticket',
submit_label: 'Submit',
elements: [{
label: 'Project',
type: 'text',
name: 'project'
}, {
label: 'Summary',
type: 'text',
name: 'summary',
}, {
label: 'Description',
type: 'textarea',
name: 'description',
optional: true,
}, {
label: 'Type',
type: 'select',
name: 'type',
options: issuetypes,
}, {
label: 'Reporter',
type: 'select',
name: 'reporter',
optional: true,
options: [{
label: 'Reporter',
value: 'reporter'
}, ],
}, {
label: 'Link',
type: 'select',
name: 'epic',
optional: true,
options: [{
label: 'Epic',
value: 'epic'
}, ],
}, ],
}),
};
Then I call dialog.open
axios.post("https://slack.com/api/dialog.open", qs.stringify(dialog))
.then(
(result) => {
res.send('');
}).catch(function(err) {
console.error(err);
})
}).catch(function(err) {
console.error(err);
})
});
Any ideas as to why dialog.open does not work?
The reason the Dialog is not shown when you have the variable in the title is that you exceed the maximum length of 24 chars for a title. (see here for reference)
You should however received the validation error from the API though as documented for the dialog.open method:
"The field `title` cannot be longer than 24 characters"
There must be another reason why you are not receiving it.

Hide controls based on selected value

For the sample code below (look here for full plunker), how can I hide the "Driver's License Number" textbox if the selected value in the "Province/Territory" dropdown is not equal to 'ontario'? The current behaviour is to disable the "Driver's License Number" textbox. So I would like to hide the textbox rather than disable it.
(function() {
'use strict';
angular
.module('formlyApp')
.controller('MainController', MainController);
function MainController(province) {
var vm = this;
// The model object that we reference
// on the <formly-form> element in index.html
vm.rental = {};
// An array of our form fields with configuration
// and options set. We make reference to this in
// the 'fields' attribute on the <formly-form> element
vm.rentalFields = [
{
key: 'first_name',
type: 'input',
templateOptions: {
type: 'text',
label: 'First Name',
placeholder: 'Enter your first name',
required: true
}
},
{
key: 'last_name',
type: 'input',
templateOptions: {
type: 'text',
label: 'Last Name',
placeholder: 'Enter your last name',
required: true
}
},
{
key: 'email',
type: 'input',
templateOptions: {
type: 'email',
label: 'Email address',
placeholder: 'Enter email',
required: true
}
},
{
key: 'under25',
type: 'checkbox',
templateOptions: {
label: 'Are you under 25?',
},
// Hide this field if we don't have
// any valid input in the email field
hideExpression: '!model.email'
},
{
key: 'province',
type: 'select',
templateOptions: {
label: 'Province/Territory',
// Call our province service to get a list
// of provinces and territories
options: province.getProvinces()
},
hideExpression: '!model.email'
},
{
key: 'license',
type: 'input',
templateOptions: {
label: 'Driver\'s License Number',
placeholder: 'Enter your drivers license number'
},
hideExpression: "(!model.province == 'ontario')",
validators: {
// Custom validator to check whether the driver's license
// number that the user enters is valid or not
driversLicense: function($viewValue, $modelValue, scope) {
var value = $modelValue || $viewValue;
if(value) {
// call the validateDriversLicense function
// which either returns true or false
// depending on whether the entry is valid
return validateDriversLicence(value)
}
}
}
},
{
key: 'insurance',
type: 'input',
templateOptions: {
label: 'Insurance Policy Number',
placeholder: 'Enter your insurance policy number'
},
hideExpression: '!model.under25 || !model.province',
}
];
// Tests the input based on a helpful regular expression
// gratefully borrowed from jQuery.formance by Omar Shammas
// https://github.com/omarshammas/jquery.formance
function validateDriversLicence(value) {
return /[A-Za-z]\d{4}[\s|\-]*\d{5}[\s|\-]*\d{5}$/.test(value);
}
}
})();
Is this possible?
Thanks in advance,
P.S: Fill the form the see the "Province/Territory" dropdown
http://plnkr.co/edit/97pINzLnz3W1HWmy9N0u?p=preview
Change
hideExpression: '!model.province'
To
hideExpression: 'model.province != "ontario"'

adding a createdBy field to the User model in keystone.js

I got the 'createdBy' field added to the model but it allows the admin to select all users as the 'createdBy' user. I want this field to be auto populated with the admin that is currently logged in and can't seem to get it to work.
Ideally this wouldn't appear in the UI at all but just be stored when the user is saved.
User.add({
name: { type: Types.Name, required: true, index: true },
email: { type: Types.Email, initial: true, required: true, index: true },
company: { type: String, required: true, index: true, initial: true },
phone: { type: String, required: true, index: true, initial: true },
password: { type: Types.Password, initial: true, required: true },
createdBy: { type: Types.Relationship, initial:true, required:true, ref: 'User' },
createdAt: { type: Date, default: Date.now }
}, 'Permissions', {
level : { type: Types.Select, numeric: true, options: [{ value: 1, label: 'User' }, { value: 2, label: 'Group Administrator' }, { value: 3, label: 'System Administrator' }] }
},
'Screening', {
rooms : { type: Types.Select, numeric: true, options: [{ value: 1, label: 'Screening room 1' }, { value: 2, label: 'Screening room 2' }, { value: 3, label: 'Screening room 3' }] }
});
While your implementation is functional, a number of Keystone developers (myself included) have raised concerns regarding the security risk of sending the user.id via a POST. You are also correct when you say that currently there is no good way of doing this in Keystone.
My solution was to implement the feature on Keystone itself. I added an optional meta pattern, which I called audit meta. This adds two fields to the List (createdBy and updatedBy) which I populate in the UpdateHandler() using an existing cached copy of req.user. This way there's no need to send user._id via POST.
To use it you just add List.addPattern('audit meta'); after defining your list, just like you would if you were using the standard meta. My implementation of audit meta also adds the standard meta fields, so there's no need to use both.
To implement this I made the following changes to Keystone
First, in lib\list.js I added the following code (prefixed with +) to the addPatern() method:
List.prototype.addPattern = function(pattern) {
switch (pattern) {
...
+ case 'audit meta':
+ var userModel = keystone.get('user model');
+
+ if(!this.schema.path('createdOn') && !this.schema.path('updatedOn')) {
+ this.addPattern('standard meta');
+ }
+
+ if (userModel) {
+ this.add({
+ createdBy: { type: Field.Types.Relationship, ref: userModel, hidden: true, index: true },
+ updatedBy: { type: Field.Types.Relationship, ref: userModel, hidden: true, index: true }
+ });
+ this.map('createdBy', 'createdBy');
+ this.map('modifiedBy', 'updatedBy');
+ }
+ break;
+
}
return this;
Then in lib/updateHandler.js I added the following code to UpdateHandler.prototype.process(), just before progress() is called at then end of the method.
+ // check for audit meta fields (mapped to createdBy/modifiedBy)
+ if (this.list.mappings.createdBy && this.item.isNew) {
+ this.item.set(this.list.mappings.createdBy, this.user._id);
+ }
+ if (this.list.mappings.modifiedBy) {
+ this.item.set(this.list.mappings.modifiedBy, this.user._id);
+ }
Earlier I submitted a pull request (https://github.com/JedWatson/keystone/pull/490) to Keystone, which includes a detailed explanation of my implementation. So, if you need this urgently, you can always fork a copy of Keystone and merge my PR.
Apparently there is no good way to do this but I did come up with a work around using someone else's idea by creating a custom hidden input field. It's not ideal but will work for this project. The default value on createdBy is just so I can make it a required field but it is populated in the form jade template not he initial jade template for that input type.
User.add({
name: { type: Types.Name, required: true, index: true },
email: { type: Types.Email, initial: true, required: true, index: true },
company: { type: String, required: true, index: true, initial: true },
phone: { type: String, required: true, index: true, initial: true },
password: { type: Types.Password, initial: true, required: true },
createdBy: { type: Types.Admin, required: true, initial: true, default: 'createdBy' },
createdAt: { type: Types.Hidden, default: Date.now }
}, 'Permissions', {
level : { type: Types.Select, numeric: true, options: [{ value: 1, label: 'User' }, { value: 2, label: 'Group Administrator' }, { value: 3, label: 'System Administrator' }] }
},Screening', {
rooms : { type: Types.Select, numeric: true, options: [{ value: 1, label: 'Screening room 1' }, { value: 2, label: 'Screening room 2' }, { value: 3, label: 'Screening room 3' }] }
});
then the custom fieldtype just something like this, just create one for form and initial. Also create the fieldTypes/admin.js and update the fieldTypes.index.js
Input admin/form.jade
.field(class='type-' + field.type, data-field-type=field.type, data-field-path=field.path, data-field-collapse=field.collapse ? 'true' : false, data-field-depends-on=field.dependsOn, data-field-noedit=field.noedit ? 'true' : 'false')
- var value = field.format(item)
.field-ui(class='width-' + field.width)
if field.noedit
.field-value= user._id
else
input(type='hidden', name=field.path, value=user._id, autocomplete='off').form-control
if field.note
.field-note!= field.note

combobox's Value is not load in extjs MVC

I am working with ExtJS MVC and implementing Scheduler.
I want to load my Store in my combo box but it was not load successfully.
My Store is
Ext.define('gantt.store.serviceStore', {
extend: 'Ext.data.Store',
model: 'gantt.model.Service',
storeId: 'serviceStore',
autoLoad: true,
autoSync: true,
proxy: {
type: 'ajax',
api: {
read: 'Event/Get'
},
reader: {
type: 'json',
root: 'data'
},
writer: {
type: 'json',
encode: true,
writeAllFields: true,
root: 'data'
}
}
});
My Model is
Ext.define('gantt.model.Service', {
extend: 'Sch.model.Event',
fields: [{ name: 'ServiceId' },
{ name: 'ServiceName' },
{ name: 'Description' },
{ name: 'Rate' }
],
proxy: {
type: 'ajax',
api: {
read: 'Service/Get'
},
reader: {
type: 'json',
root: 'data'
},
writer: {
root: 'data',
type: 'json',
encode: true,
writeAllFields: true
}
}
});
and My ComboBox Code is below..
this.combo = new Ext.form.ComboBox({
id: 'statesCombo',
store: 'serviceStore',
displayField: 'ServiceName',
valueField: 'ServiceName',
hiddenName: 'ServiceId',
typeAhead: true,
mode: 'local',
fieldLabel: 'Services',
anchor: '100%',
forceSelection: true,
triggerAction: 'all',
emptyText: 'Select a Service',
selectOnFocus: true })
My Problem is when I am Click on combo box my value is not loaded..
and didnt display any Error.
You're missing the "name" option... Like this:
name: 'ServiceName',

Resources