parsley.js: Error trying to add custom validator - parsley.js

I am trying to add a custom validator
window.ParsleyValidator
.addValidator('invalidWords', {
requirementType: 'regexp',
validateString: function(value, requirement) {
console.log(value,requirement);
return /^\b(?:Stadium|GT|BB|HB|Simul|VNOSE|LT|combination|LT1|SSGT|BW|HBS|simul|combo|2hbs|4d|lt2|theatre)\b$/i.test(value)
},
messages: {
en: 'Invalid words detected.'
}
});
with HTML as...
<div class="col-sm-6 col-lg-6">
<div class="form-group">
<input type="text" name="company" data-parsley-group="eventinfo" id="Company" class="form-control" placeholder="Company" maxlength="60" tabindex="3" title="Company" parsley-trigger="keyup" data-parsley-invalidwords="" value="#request.args.company#">
</div>
</div>
I keep getting the error Callback must be instanciated with a function and I am not sure why. I am following the directions on the site. http://parsleyjs.org/doc/index.html#custom
It also doesn't seem to trigger on keyup either.
using version 2.0.7

I noticed I was on an older version so I have updated to 2.2-rc4 and the issue seems to be resolved.

Related

Submitting user feedback data to Elasticsearch

I'm trying to use this angular bootstrap feedback form to collect user feedback data and index the information to Elasticsearch (to make it searchable).
So in my searchService for Elasticsearch, I simply did:
this.userSearchFeedback = function (userFeedbackForm) {
esClient.index({
index: 'searchfeedback-index1',
type: 'general',
opType: 'index',
refresh: true,
body: {
fields: ['comments', 'email']
}
}).then(function(es_return) {
console.log('success');
}, function(error) {
console.log('error');
});
};
userFeedbackForm is the name of the form, which looks like this:
<div class="row">
<div class="col-xs-12">
<div class="alert alert-info" role="alert">
We would love to hear your thoughts and suggestions on what we get right and wrong - it helps us improve our services to you. Your feedback is appreciated and helps us get better!
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6">
<!-- DESCRIPTION -->
<div class="form-group">
<pre>Model: {{comments | json}}</pre>
<label for="description_field" class="control-label">Comment:</label>
<textarea class="form-control" placeholder="Please describe your issue or share your feedback!" name="comments" ng-model="comments" style="min-height: 165px;"></textarea>
</div>
<!-- /DESCRIPTION -->
<!-- EMAIL -->
<div class="form-group">
<pre>Model: {{email | json}}</pre>
<label for="email_field" class="control-label">Email:</label>
<input type="text" class="form-control" placeholder="Email" name="email" ng-model="email" />
</div>
<!-- /EMAIL -->
</div>
I've added ng-models for both inputs and added those in my controller
//initialize feedback form
$scope.feedback = {
comments: '',
email: ''
};
The module already comes with a function that is called from ng-click on the form template...
function submitButtonPressed(form) {
console.log("Submit button pressed");
console.log(form);
console.log($scope.feedback.comments);//added
console.log($scope.feedback.email);//added
and that is where I'm stuck.
What else do I need to do with the function in order for it to call the userSearchFeedback() in my searchService so that the form data can be indexed to ES?
After just trial and error with the above posted. I decided to look to see if there was something else available. There is and its amazingly simple to implement. Just add the url to submit to and your done! Had it up and running in just a few minutes (once I realized I had to supply a url).
HTH anyone.

How to get the uib-popover to open or close when the focus of the input field changes

I have a input field that has the uib-popover control on it. I have followed the documentation on how to get the directive to open but I have noticed some discrepancies in the documentation as well as examples on plnker and SO questions here.
Within my hmtl I have the inputs set as follows:
<div class="form-group col-xs-6 col-sm-6 col-md-6 col-lg-6">
<label>Password</label><input type="{{user.inputType}}" ng-blur="user.validatePassword(user.newUser.password, user.newUser.confirmPassword)" placeholder="Enter Password" id="password" required class="form-control" ng-model="user.newUser.password" uib-popover-template="'myPopoverTemplate.html'" uib-popover-trigger="'focus'"/>
</div>
<div class="form-group col-xs-6 col-sm-6 col-md-6 col-lg-6">
<label>Confirm Password</label>
<input type="{{user.inputType}}" ng-keyup="user.validatePassword(user.newUser.password, user.newUser.confirmPassword)" placeholder="Confirm Password" id="confirmPassword" required class="form-control" ng-model="user.newUser.confirmPassword"/>
<span style="color: red">{{user.message}}</span>
</div>
Most examples as well as the SO questions on here are using an older library as attributes are not prefaced with uib-*.
This code/directive currently works and renders but it only work or appears when clicking in the field and then clicking in the same field to close the popover. I have tried both the focus trigger and the oustsideClick trigger. Both have the same result of not rendering or closing the popover unless clicking in the field.
versions of the frameworks used are:
angularjs 1.5.8
ui-bootstrap 1.3.3
Changing the trigger to match earlier examples were popover-trigger is used vs. uib-popover-trigger is used disables the popover
I have created a working plunker that demonstrates what is happening.
Any suggestions on what I am missing or what I need to change.
Thanks in advance
According to tooltip.js description, in order to set a custom trigger,
it needs to be specified via trigger option passed to the $tooltipProvider.options method. In your case for focus trigger it will be:
app.config(['$uibTooltipProvider', function ($uibTooltipProvider) {
$uibTooltipProvider.options({ trigger: 'focus' });
}]);
Updated plunker that shows how to trigger tooltip on focus handler.
There's a problem of your code, please modify like below:
app.js:
(function() {
var app = angular.module('app', ['ui.bootstrap']);
app.controller('main',[ '$scope', main]);
function main($scope)
{
vm = this;
vm.message = 'hello';
vm.dynamicPopover = {
content: 'Hello, World!',
templateUrl: 'myPopoverTemplate.html',
title: 'Title'
};
}
}());
index.html
<input class="form-control" uib-popover-template="vm.dynamicPopover.templateUrl" popover-trigger="focus"/>
Actually, you can not just pass the template's id to the uib-popover-template attribute, you need to create an object to map it waited to pass.

parsley js - conditional required if checkbox checked

Is there an easy way with parsleyjs to make a field required depending on another field?
See my js fiddle here http://jsfiddle.net/marksteggles/wbhLq0t4/1/
<form data-parsley-validate="true">
<div class="form-group">
<label>
<input name="request_signature" type="checkbox" />Require signature</label>
<div class="request_signature_fields">
<textarea class="form-control required" name="signature_reason" rows="3"></textarea>
</div>
</div>
<input class="btn btn-success" name="commit" type="submit" value="Send" />
</form>
Minimally as of 2.2.0 you can create a custom validator:
window.Parsley.addValidator("requiredIf", {
validateString : function(value, requirement) {
if (jQuery(requirement).val()){
return !!value;
}
return true;
},
priority: 33
})
This gets applied in such a way:
<textarea
class="form-control required"
name="signature_reason"
rows="3"
data-parsley-validate-if-empty="true"
data-parsley-required-if="#my-field-to-check"
></textarea>
Explanation
data-parsley-required-if is the custom validator we just defined. It takes any arbitrary jQuery selector and if that field contains a non-falsy value it ensures that this field is not empty.
data-parsley-validate-if-empty is needed to ensure that the field is being validated at all, because Parsley does not validate empty non-required fields by default.
More data on custom validators here: http://parsleyjs.org/doc/index.html#custom
There is no easy way yet (see this and this).
You can either toggle the attribute required with Javascript, or listen to the right parsley events on one field and check the other field.
Just incase anyone else is trying to work this out. The best way does seem to be altering the required attribute then clearing the values.
I used this:
HTML:
<input id="checkbox-id" type="checkbox">
<div id="conditional-inputs" style="display:none;">
<input type="text" name="somename" />
<input type="text" name="othername" />
<input type="text" name="onemoreforluck" />
</div>
jQuery:
$("#checkbox-id").change(function() {
if(this.checked) {
$('#conditional-inputs').slideDown();
/* use .slideDown to display conditional input block */
$("#conditional-inputs :input").prop('required', true);
/* set required attribute on all inputs inside conditional area */
}
else{
$('#conditional-inputs').slideUp();
/* use .slideUp to hide conditional input block */
$("#conditional-inputs :input").prop('required', false).val('');
/* remove required attribute on all inputs and empty values of inputs */
}
})
I realise that this question was asked and answered in 2012, and is most likely related to the ParsleyJS v1, while the most recent version at the time of writing this is v2.2.0. However I had to do some work on an old form that used v1 and I found that conditionals are possible (with a little bit of jQuery). So here's to anyone who might still need this.
You can dynamically add and remove form elements and constraints (read: validation rules) using the following:
$('#form').parsley('addItem', '#input_id');
$('#form').parsley('removeItem', '#input_id');
$('#input_id').parsley('addConstraint', '{ required: true }');
$('#input_id').parsley('removeConstraint', 'required');
So using jQuery listeneners for when the checkbox changes we can execute this kind of code which will add the signature field as a required field. Here it is in action for the question.
< script src = "js/parsley-v1.js" > < /script>
<script>
$('#request_signature').on('click', function() {
if($(this).is(':selected')) {
$('#signature_form').parsley('addItem', '#signature_reason');
$('#signature_reason').parsley('addConstraint', { required: true });
} else {
$('#signature_reason').parsley('removeConstraint', 'required' });
$('#signature_form').parsley('removeItem', '#signature_reason');
}
});
</script >
<form id="signature_form" data-parsley-validate="true">
<div class="form-group">
<label>
<input id="request_signature" name="request_signature" type="checkbox" />Require signature</label>
<div class="request_signature_fields">
<textarea id="signature_reason" class="form-control" name="signature_reason" rows="3"></textarea>
</div>
</div>
<input class="btn btn-success" name="commit" type="submit" value="Send" />
</form>
You can also hide the parts that are not required anymore, or disable the fields that are not needed, and add [disabled] and :hidden to the excluded Parsley option.
{
excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden], [disabled], :hidden',
}
NB: you don't need to hide each field, hiding a parent div is enough.
I found a good example that I forked here
➡️ http://jsfiddle.net/capripot/xoaLs4bt/
This should be possible with the great little Parsley addon plugin found here: http://themonk.github.io/parsely-conditions/
I found the shortest method -
$('input[type=radio][name=nlcsu]').change(function() {
// I am checking for a Radio button
if (this.value == 1) {
$("#nlcsu_post").attr('required', '1');
$("#nlcsu_year").attr('required', '1');
} else if (this.value == 0) {
$("#nlcsu_post").removeAttr('required');
$("#nlcsu_year").removeAttr('required');
}
});

AngularJS binding datatimepicker selected value to ng-model

I have a newbie AngularJS question - I am using a datetimepicker library and I'm having a hard time getting the date selected to bind to my model... I saw some posts talking about not being able to access the datetimepicker model directly, but in my case I find that if I just manually TYPE IN a text value in my date input box, it binds! If I select a date with the chooser, I get the dreaded 'undefined' :(... help?
HTML markup:
<div class="col-md-2">
<div name="fromDateTime" class="input-group date" id="datetimepickerFrom">
<input class="form-control" type="text" name="fromDateTime" ng-model="formEntries.fromDateTime"/>
<span class="input-group-addon" data-ng-click="pickFromDateTime()"><span class="glyphicon glyphicon-calendar" id="calIconFrom"></span></span>
</div>
</div>
<div class="col-md-2">
<div name="toDateTime" class="input-group date" id="datetimepickerTo">
<input class="form-control" type="text" name="toDateTime" ng-model="formEntries.toDateTime"/>
<span class="input-group-addon" data-ng-click="pickToDateTime()"><span class="glyphicon glyphicon-calendar"></span></span>
</div>
</div>
Controller:
$scope.pickFromDateTime = function () {
$("#datetimepickerFrom").datetimepicker();
$("#datetimepickerFrom").datetimepicker().change(function() {
$(this).data("DateTimePicker").hide();
console.log($(this).data("DateTimePicker").getDate());
});
}
$scope.pickToDateTime = function () {
$("#datetimepickerTo").datetimepicker();
$("#datetimepickerTo").datetimepicker().change(function() {
$(this).data("DateTimePicker").hide();
console.log($(this).data("DateTimePicker").getDate());
});
}
$scope.getData = function() {
console.log($scope.formEntries.fromDateTime);
console.log($scope.formEntries.toDateTime);
}
Never ever ever write DOM or jQuery code in your controller. It will never work properly. You must create a directive to do this. The directive will listen to events from whatever library you're using and update your model. Here is an example of a directive that happens to work with the datepicker. This should get you on the right track.

Form Validation error while using angularjs

I'm trying to add a simple validation for my input text box using angularjs and trying to show an inline error message. I have tried a lot, but still I'm not able to get the $valid, $ error, $invalid etc. These attributes are getting as undefined. I have given the reference to angularjs.js file. All other functionalities are working, but don't know what's happening. I'm new to angularjs, hope someone will help me in this regard. My code snippet is given below.
<sp-modal-dialog show='modalShown'>
<label for="title">Title <span>*</span></label>
<input type="text" name="txtTitle" ng-model="Model.Title" ng-maxlength="20" required>
<div ng-show="popupForm.txtTitle.$invalid">Invalid:
<span ng-show="popupForm.txtTitle.$error.required">Title is mandatory.</span>
<span ng-show="popupForm.txtTitle.$error.maxlength">Title should contain atleast 20 characters.</span>
</div>
EDIT:
I'm using a directive to show the popup form. Please see the code below.
//Directive to link the modalDialog as Element
contextualHelpModule.directive('spModalDialog', function () {
return {
restrict: 'E',
scope: {
show: '='
},
replace: true,
transclude: true,
link: function (scope, element, attrs) {
scope.hideModal = function () {
scope.show = false;
};
},
template: '<form id="popupForm" name="popupForm" novalidate><div ng-show="show"><div class="popup-main" ng-show="show"><div class="popup-container"><div class="popup-content" ng-transclude><div ng-click="hideModal()" class="popup-close">X</div></div></div></div><div class="popup-overlay"></div></div></form>'
};
you need to wrap that into a form:
<form name="popupForm">
<label for="title">Title <span>*</span></label>
<input type="text" name="txtTitle" ng-model="Model.Title" ng-maxlength="20" required>
<div ng-show="popupForm.txtTitle.$invalid">Invalid:
<span ng-show="popupForm.txtTitle.$error.required">Title is mandatory.</span>
<span ng-show="popupForm.txtTitle.$error.maxlength">Title should contain atleast 20 characters.</span>
</div>
</form>
I hope that it helps.
Yes, as jvrdelafuente explains, you will need to wrap it in a
<form name="popupForm">
tag. Once you do that, then you will have access to the properties via popupForm.txtTitle.$error.required, etc. Otherwise, they are not defined as you have observed. Unfortunately, I have recently learned that if you are placing your form tag in an aspx page using a SharePoint master page, the master page places its own form tag without a name attribute. ASP.NET will then strip your form out because it does not allow a form within a form. I am still searching for the rest of the story.
Update....
To be able to get past the issue with ASP.NET stripping out the AngularJS form tag, use an ng-form tag instead:
<ng-form name="popupForm">
<label for="title">Title <span>*</span></label>
<input type="text" name="txtTitle" ng-model="Model.Title" ng-maxlength="20" required>
<div ng-show="popupForm.txtTitle.$invalid">Invalid:
<span ng-show="popupForm.txtTitle.$error.required">Title is mandatory.</span>
<span ng-show="popupForm.txtTitle.$error.maxlength">Title should contain atleast 20 characters.</span>
</div>
</form>
Use ng-form at place of form, it will work fine, as see code in below
<ng-form name="popupForm">
<label for="title">Title <span>*</span></label>
<input type="text" name="txtTitle" ng-model="Model.Title" ng-maxlength="20" required>
<div ng-show="popupForm.txtTitle.$invalid">Invalid:
<span ng-show="popupForm.txtTitle.$error.required">Title is mandatory.</span>
<span ng-show="popupForm.txtTitle.$error.maxlength">Title should contain atleast 20 characters.</span>
</div>
</ng-form>

Resources