In my web front end form, I am using checkbox to select list of companies for each checkbox entry, I have given company name as 'value' attribute. In nodejs, I use express-validator to check the form. I am not clear how to validate and sanitize user input for these checkbox items.
I see all the example of express validator uses form parameter name to check a specific parameter (eg) check('userName') as middleware. But for checkboxes particular parameter will be present only when the user select that parameter. If I have 10 options and user select only 4 of them, then req.body will have only these parameters . And also I want all them pass through same validation check and sanitization. Please suggest how to do it.
I am using NodeJS version: 10.8
Express Validator: 5.3.0
My checkbox values are company_a1,company_a2,...company_a10. I tried to write custom Validator and check for each of the body parameter for alphanumeric value, but check is not raising error even if the value contain alphanumeric strings
async function validateReportParams(body, { req, loc, rpath }) {
for (const par of Object.keys(req.body)) {
try {
check(req.body[par].isAlphanumberic());
} catch (err) {
return Promise.reject(err);
}
}
}
exports.genReport = [
validateReq,
param().custom(validateReportParams),
async (req, res, next) => { ... }
];
Try using the same name for each checkbox than apply isIn([]) to validate as per: https://express-validator.github.io/docs/check-api.html
check(req.body.checkbox.isIn(['company_a1','company_a2',...,'company_a10']));
My answer is a little unrelated to this question.
but if you want to use an optional checkbox in your form.
you can do something like this
body('checkbox')
.customSanitizer(input => {
return Boolean(input)
})
Related
I am using an intent to first present the carousel to the user.
When the user clicks on one of the options in the carousel, in the handler intent I get the key of the carousel item that the user selected.
Example of carousel intent,
app.intent('search', async (conv,params) => {
conv.ask(`Choose one item`,new Carousel({
title :`Search results`,
items : carouselItems,
}));
});
Example of the handler intent,
app.intent('handle_carousel', async (conv,params,option) => {
const key = parseInt(option);
});
However, along with the key of the option selected I also want to pass another integer from the carousel intent to the handler intent.
This other integer is different for each option. You can think of the other integer as an ID, it's unique for each option.
How can I achieve that?
You have a few approaches for passing additional data that should be associated with each key.
The first is, as you note in your answer, storing that mapping in a table that is stored as part of session data (either using conv.data or a Dialogflow context).
Another is to encode that data as part of the key that you include with each option, and then decode the key when you get it back.
So, for example, you could make the key a result of an encode function like
function encodeOptionKey( key, otherValue ){
return `${key}:${otherValue}`
}
and then decode it with a function such as
function decodeOptionKey( option ){
const [key,otherValue] = option.split(':');
return {
key,
otherValue
}
}
and call this from your handler with something like
app.intent('handle_carousel', async (conv,params,option) => {
const {key, otherValue} = decodeOptionKey( option );
// ...
});
I created a map of the keys of various carousel options and the corresponding parameter I wanted to pass, saved that map in conv.data.store, which is the conversation storage provided by actions-on-google. Then I used that map to get the parameter from the carousel key that was being passed to the handler intent.
For example in the carousel intent :
let map = {
keyofcarousel : option,
other_parameter : otherparam,
};
conv.data.store = map;
Then call conv.data.store in the handler intent.
Using code, I am trying to create a "Widget" Content-Type called FeaturedProperties with an editable field called MaxVisibleField. I want the MaxVisibleField field to show up under the Fields section when editing the content-type.
I used migration to create a new Contact-Part called MaxPropertiesToShow and created a field called MaxVisibleField for the MaxPropertiesToShow part.
I am expecting the MaxVisibleField field to show up when the “Widget” is edited in the admin panel. When I edit the FeaturedProperties content-type, I see no fields listed. However, I do see the part.
What else do I need to do to make my field MaxVisibleField show up when my Widget is being edited?
Here is my migration code
public int Create()
{
_contentDefinitionManager.AlterPartDefinition("MaxPropertiesToShow", (part) =>
{
part.WithField("MaxVisibleField", c =>
{
c.OfType(nameof(NumericField))
.WithDisplayName("Max Properties To Show")
.WithDescription("The app with display up to this many properties")
.WithSettings(new NumericFieldSettings()
{
Required = true,
Maximum = 50,
DefaultValue = "8",
});
});
});
_contentDefinitionManager.AlterTypeDefinition("FeaturedProperties", (type) =>
{
type.Stereotype("Widget")
.Creatable(false)
.Listable(false)
.Versionable(false)
.WithPart(nameof(FeaturedPropertyPart));
});
return 1;
}
Here is a screenshot of what I am seeing
Also, in the Widget-FeaturedProperties.cshtml view, how can I render the title in a place I want it to show up instead of the standard position the app displays it in?
I have a custom form where, in a subtab, I have a dropdown that I need to find out the selected value on the client side after the user selects to perform some validation. I created the script and tied it to the on change event of the dropdown. I cannot seem to find the code to get the selected value on the client side. I have found code to read the value on the server side from a submit event. I need this on the client side on change. I am going to use the ID to look up a record and check a value on that record and if applicable popup a warning to the user. Either SS1 or SS2 is good, whatever would be better I have both available. Any help with this would be great. thanks
In a client script, you can use nlapiGetFieldValue() to retrieve the results.
function fieldchanged(type, name, linenum) {
if(name == 'dropdownid') {
var value = nlapiGetFieldValue('dropdownid');
alert(value);
}
}
OK the nlapiGetFieldValue, did not do the trick, what did was the following
function ValidateField( type, field, linenum ) {
if ( field === 'recordid' ) {
var vendorid = nlapiGetCurrentLineItemValue(type,field,linenum);
var vendorRecord = nlapiLoadRecord('vendor',vendorid);
}
return true;
}
thanks for your help
I have a form with an extra unbound field added using 'property_path' => false.
I would like to have a simple validation on this field and I've found many answers that suggest to use something like
$builder->addValidator(...);
but I've seen that in symfony 2.1 $builder->addValidator is deprecated. Does anyone know what is the correct way to put a validation on an unbound field in Symfony 2.1?
Edit :
I've just made a more complete answer on topic Symfony validate form with mapped false form fields
Original answer
Validating unbound (non mapped) field in a form is not well documented and the fast evolving form and validator components make the few examples obsoletes (for Symfony 2.1.2).
For now I succeed in validated non mapped fields with event listener.
Here is my simplified code :
namespace Dj\TestBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Dj\TestBundle\Form\EventListener\NewPostListener;
class PostType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('lineNumber', 'choice', array(
'label' => 'How many lines :',
'choices' => array(
3 => '3 lines',
6 => '6 lines'
),
// 'data' => 3, // default value
'expanded' => true,
'mapped' => false
))
->add('body', 'textarea', array(
'label' => 'Your text',
'max_length' => 120));
// this listener will validate form datas
$listener = new NewPostListener;
$builder->addEventListener(FormEvents::POST_BIND, array($listener, 'postBind'));
}
// ... other methods
}
And the event listener :
namespace Dj\TestBundle\Form\EventListener;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormError;
/**
* listener used at Post creation time to validate non mapped fields
*/
class NewPostListener
{
/**
* Validates lineNumber and body length
* #param \Symfony\Component\Form\FormEvent $event
*/
public function postBind(FormEvent $event)
{
$form = $event->getForm();
$data = $event->getData();
if (!isset($data->lineNumber)) {
$msg = 'Please give a correct line number';
$form->get('lineNumber')->addError(new FormError($msg));
}
// ... other validations
}
}
This is how I validate my non mapped fields until I find out how to do this with validators.
I have the same problem from the docs we get this:
The interface FormValidatorInterface was deprecated and will be
removed in Symfony 2.3. If you implemented custom validators using
this interface, you can substitute them by event listeners listening
to the FormEvents::POST_BIND (or any other of the *BIND events). In
case you used the CallbackValidator class, you should now pass the
callback directly to addEventListener.
This suggest to use event listeners but I have not found and example.
https://github.com/symfony/symfony/blob/master/UPGRADE-2.1.md
I am trying to append a string to the body field of a CCK node after it has been submitted or edited. However, I'm having trouble working with the body field in the form alter. My initial attempt was to modify the body field in the submit handler by using the .operator to append a string to the body field.
//Calling this submit function to add string to body.
function appendToBody_submit_function($form, &$form_state) {
$form_state['values']['body'] = array('0' => array('value' => $form['#body'])) . $stringToAppend;
}
However, I can't get this to work, and I'm not sure it's the right way. I am new to Drupal, Can someone point me in the right direction? Should I be using node_api for this?
I assume that you add your custom submit callback to the forms #submit array via hook_form_alter().
If you add it before any other entry in that array (as opposed to just appending it), your callback should be called before the standard submit function. That way, all you need to do is adjust the $form_state['values']['body'] content 'in place', and it will be picked up (and subsequently saved) on further processing by the standard submit callback implicitly:
/**
* Implementation of hook_form_alter()
*/
function yourModule_form_alter(&$form, $form_state, $form_id) {
// Is this a node edit form?
if (isset($form['type']) && isset($form['#node']) && $form['type']['#value'] .'_node_form' == $form_id) {
// Yes, add custom submit handler *before* already existing ones
array_unshift($form['#submit'], 'appendToBody_submit_function');
}
}
// Custom submit function to add string to body.
function appendToBody_submit_function($form, &$form_state) {
$form_state['values']['body'] = $form_state['values']['body'] . $stringToAppend;
}
I recommend installing the Devel module so you can easily print out the contents of $form_state by placing dpm($form_state); in your method body. I usually start with that to make sure the values are where/what I expect.
// Replace "hook" in the function name with the name of your module.
function hook_submit($form, &$form_state) {
// dpm($form_state); // Debug code to view the contents of $form_state.
$body = $form_state['values']['body'] . ' new string to append';
// Place code to save this data to your database here.
}