Hide controls based on selected value - angular-formly

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"'

Related

How to set a default value in GRAPHQL

I wanna set a default value in the role property but I don´t know how to do it.
The idea is that the role property is "BASIC" by default for all users.
I´m using express.
Sorry for my english, I´m not native, this is the code:
const UserType = new GraphQLObjectType({
name: "User",
description: "User type",
fields: () => ({
id: { type: GraphQLID },
username: { type: GraphQLString },
email: { type: GraphQLString },
displayName: { type: GraphQLString },
phone: { type: GraphQLString },
role: { type: GraphQLString}
}
),
});
thank you!
This is done with the defaultValue property. But this is not possible for the GraphQLObjectType as you show.
const UserType = new GraphQLObjectType({
name: 'User',
description: 'User type',
fields: () => ({
id: { type: GraphQLID },
username: { type: GraphQLString, defaultValue: 'default string' },
}),
});
Object literal may only specify known properties, and 'defaultValue' does not exist in type 'GraphQLFieldConfig<any, any, { [argName: string]: any; }>'
So GraphQLObjectType has no default Value property.
You need to solve this in a different place, not here. For example, when using data, if the value you want is empty, you can use default instead.
...
...
data.username ?? 'default string'
...
...
But where does this defaultValue property work? It works with GraphQLInputObjectType.
For example:
const filter = new GraphQLInputObjectType({
name: "Filter",
fields: () => ({
min: { type: new GraphQLNonNull(graphql.GraphQLInt) },
max: { type: graphql.GraphQLBoolean, defaultValue: 100 },
}),
});
and we can use it like this:
...
query: {
products: {
type: new GraphQLList(productTypes),
args: { filter: { type: new GraphQLNonNull(filter) } }, // <-----
resolve: allProducts,
},
},
...
This is already answered on https://stackoverflow.com/a/51567429/10310278
And official documentation https://graphql.org/graphql-js/type/#example-5
Please check these things out.

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.

Node.js dependson access relationship attribute?

I have two simple modes:
PresentationType:
var keystone = require('keystone');
var PresentationType = new keystone.List('PresentationType', {
autokey: { from: 'name', path: 'key', unique: true },
});
PresentationType.add({
name: { type: String, required: true },
t1: { type: Boolean },
t2: { type: Boolean },
});
PresentationType.relationship({ ref: 'StaticPage', path: 'pages', refPath: 'presentationType' });
PresentationType.register();
Static Page:
var keystone = require('keystone');
var Types = keystone.Field.Types;
var StaticPage = new keystone.List('StaticPage', {
map: { name: 'title' },
autokey: { path: 'slug', from: 'title', unique: true },
drilldown: 'presentationType',
});
StaticPage.add({
title: { type: String, required: true },
presentationType: { type: Types.Relationship, ref: 'PresentationType', many: false },
text1: { type: String, dependsOn: { presentationType.t1: true } },
text2: { type: String, dependsOn: { presentationType.t2: true } },
});
StaticPage.defaultColumns = 'title';
StaticPage.register();
First i create a presentation type that has boolean attributes, text1 and text2
Secondly when i create a page and specify it's presentation type, i want to be able to display certain fields based on the presentation type boolean.
So far i cant seem to find an answer to it.
The dependsOn attribute cannot be used across a relationship field; that field would constantly need to be populated with that relationship. dependsOn within a model can only be used within other static fields of the same model (and not across different models.)
http://keystonejs.com/docs/database/#fields-conditional

how to set validation in 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

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

Resources