I'm trying to get the value of each checked box that has been selected as true. Each time I select a checkbox it grabs the value of that checkbox instead of all the selected checkboxes.
Path: talentList.html
<fieldset>
<div class="checkbox">
<label>
<input name="specialisation" type="checkbox" value="Accounting Firm"> Accounting Firm
</label>
</div>
<div class="checkbox">
<label>
<input name="specialisation" type="checkbox" value="Accounting in Industry"> Accounting in Industry
</label>
</div>
</fieldset>
Path: talentList.js
Template.talentList.events({
'change [name="specialisation"]': function ( event, template ) {
let specialisation = event.target.value;
template.candidateListFilter.set( specialisation );
}
});
There is only one target set in the event handler so event.target.value will be a scalar instead of an array. You need to iterate over the array of checkboxes.
Template.talentList.events({
'change [name="specialisation"]': function ( event, template ) {
$.each($('[name="specialisation"]'),function(i,cb){
let specialisation = cb.value;
template.candidateListFilter.set( specialisation );
});
}
});
To be honest this seems like an odd pattern. If you want to update a document whenever a checkbox is checked/unchecked you shouldn't have to set the state of all the other checkboxes at the same time, you should be able to just poke the one you want.
Not sure if this is correct. It creates an object of all selected options.
'change [name="specialisation"]': function ( event, template ) {
$(document).ready(function(){
var specialisation = $('input[name="specialisation"]:checked').map(function(){
return $(this).val();
});
var specialisationListArray = specialisation.get();
template.candidateListFilter.set( specialisationListArray );
});
},
Related
I am using a template based form in angular. I also use bootstrap (v4) and I wish to show some validation messages when the form was submitted.
This is my form:
<form [ngClass]="{'was-validated': wasValidated}">
<div class="form-group">
<label for="name">Name</label>
<input type="text" id="name" name="name" class="form-control" [(ngModel)]="category.name" #name="ngModel" required maxlength="100"/>
<div *ngIf="name.invalid" class="invalid-feedback">
<div *ngIf="name.errors.required">
Name is required.
</div>
</div>
</div>
<button type="submit" class="btn btn-success" (click)="save()">Save</button>
</form>
My component looks as follows:
category: Category;
wasValidated: boolean = false;
ngOnInit() {
this.reset();
}
save() {
this.wasValidated = true;
this.categoriesService.createCategory(this.category).subscribe(
() => {
this.notificationService.add(notifications.category_saved, {name: this.category.name});
this.reset();
},
() => this.notificationService.add(notifications.save_category_failed)
);
}
reset() {
this.wasValidated = false;
this.category = {} as Category;
}
This works, but I have a feeling it's overly complex and more like a workaround rather than the right way. What is the best way to accomplish this?
Note: the class was-validated must be present on the form element in order to show the div with class invalid-feedback. I'm using this: https://getbootstrap.com/docs/4.0/components/forms/#validation
Note 2: I have currently no mechanism yet to prevent form submission on error. I'd like to know a good solution for that as well!
With the answer from #Chellappan V I was able to construct the solution I wanted.
I have applied to following changes:
First added #form="ngForm" to the form tag in the template. Secondly I changed the ngClass expression to reference the submitted state of the form, rather than referring to a boolean which was set to true manually when form was submitted. Last but not least I pass the form in the submit method on the save button.
<form novalidate #form="ngForm" [ngClass]="{'was-validated': form.submitted}">
<!-- form controls -->
<button type="submit" class="btn btn-success" (click)="submit(form)">Save</button>
</form>
In the component I injected the template variable in the component with #ViewChild.
#ViewChild("form")
private form: NgForm;
The submit method now takes a form parameter of type NgForm which is used to check if the form was valid before sending a request to the backend:
submit(form: NgForm) {
if (form.valid) {
this.categoriesService.createCategory(this.category).subscribe(
() => {
this.notificationService.add(notifications.category_saved, {name: this.category.name});
this.reset();
},
() => this.notificationService.add(notifications.save_category_failed)
);
} else {
this.notificationService.add(notifications.validation_errors);
}
}
Finally the reset method resets the form and the model so it can be re-entered to submit a next instance:
reset() {
this.form.resetForm();
this.category = {} as NewCategoryDto;
}
I am knew to knockout and have a question about how to do some conditional binding. I have a dropdown input that shows and hides other inputs depending upon the option that is selected. I have that working but I am having a problem when I load the page after the page has already been posted previously. I am able to GET the dropdown inputs that was previously selected and posted but the binding that takes place (showing and hiding) of the other inputs is not triggered. Please see below:
<script>
function ViewModel() {
this.selectedPet = ko.observable();
var petArray = ["Dog", "Cat", "Fish"];
this.petOptions = ko.observableArray(petArray);
};
ko.applyBindings(new ViewModel);
</script>
<form>
<select data-bind="options: petOptions, value: selectedPet" asp-for="Pets">
</select>
<input data-bind="visible: petOptions() === "Dog" asp-for="DogFood" />
<input data-bind="visible: petOptions() === "Cat" asp-for="CatFood" />
<input data-bind="visible: petOptions() === "Fish" asp-for="FishFood" />
</form>
I figured out what I needed to do. I need to set the initial observable value to the value that was posted.
var onLoadPet = "#Model.Pet.Value";
function ViewModel() {
this.selectedPet = ko.observable(onLoadPet);
}
I am new to Meteor :)
I have a template helper:
userRoleMap: function() {
var u = getUser();
if (u) {
var lstRoles = Meteor.roles.find({}).fetch();
var userRoles = u.roles ? u.roles : [];
_.map(lstRoles, function(r) {
_.extend(r, {
userMapped: _.contains(userRoles, r.name)
});
return r;
});
return lstRoles;
}
return [];
}
I am using this helper in my template as:
{{#each userRoleMap}}
<div class="checkbox">
<label>
<input type="checkbox" class="chkUserRole" value="{{name}}" checked="{{userMapped}}"> {{name}}
</label>
</div>
{{/each}}
I am showing the above html/template in a bootstrap-modal. I am showing this modal on click of a button (and setting user-id in a Session which I am using when calling getUser() function).
The issue is the checkbox check state is not changing based on value of "userMapped". It is getting set correctly first time, but not afterwards. The helper userRoleMap is getting called every-time I open modal, but the checkboxes are having same checked state which they had when it was opened previously (manual checks/unchecks are getting maintained).
The return value of helper method is working as expected (verified by logging it on console).
Anything I am missing here ? Something to do with _.extend() ?
The Meteor way to do this is to either return checked as an element attribute or not:
Template.registerHelper( 'checked', ( a, b ) => {
return a === b ? 'checked' : '';
});
{{#each userRoleMap}}
<div class="checkbox">
<label>
<input type="checkbox" class="chkUserRole" value="{{name}}" {{checked userMapped true}}> {{name}}
</label>
</div>
{{/each}}
I'm using Advanced Custom Fields on my WordPress site and I have a datepicker start-date & end-date that I'm trying to set min/max on when one is selected. From jQuery's datepicker date-range I'm trying to add the onClose option.
I currently have the following code based off the custom javascript fields page but it's not working.
<?php function takeover_scripts() { ?>
<script type="text/javascript">
(function($) {
var startDate = $('.acf-field-568d4b2968a3e');
acf.add_filter('date_picker_args', function( args, startDate ){
// do something to args
args.changeMonth = false;
args.onClose = function( selectedDate ) {
$( ".acf-field-568d4bbd68a3f" ).datepicker( "option", "minDate", selectedDate );
}
// return
return args;
});
var endDate = $('.acf-field-568d4bbd68a3f');
acf.add_filter('date_picker_args', function( args, endDate ){
// do something to args
args.changeMonth = true;
args.onClose = function( selectedDate ) {
$( ".acf-field-568d4b2968a3e" ).datepicker( "option", "minDate", selectedDate );
}
// return
return args;
});
})(jQuery);
</script>
<?php }
add_action('acf/input/admin_footer', 'takeover_scripts'); ?>
I'm not sure if I need to target the id of the end-date input or the field number or if I even have the start-date field selected correctly. If anyone has any experience with this please let me know what I'm setting/selecting wrong.
Here's the markup for the two fields :
<div class="acf-field acf-field-date-picker acf-field-568d4b2968a3e" style="width:25%;" data-name="start_date" data-type="date_picker" data-key="field_568d4b2968a3e" data-required="1" data-width="25">
<div class="acf-label">
<label for="acf-field_568d479e68a3b-0-field_568d4b2968a3e">Start Date <span class="acf-required">*</span></label>
</div>
<div class="acf-input">
<div class="acf-date_picker acf-input-wrap" data-display_format="MM d, yy" data-first_day="0">
<input id="acf-field_568d479e68a3b-0-field_568d4b2968a3e" class="input-alt" type="hidden" name="acf[field_568d479e68a3b][0][field_568d4b2968a3e]" value="">
<input type="text" value="" class="input active hasDatepicker" id="dp1452127570218">
</div>
</div>
</div>
<div class="acf-field acf-field-date-picker acf-field-568d4bbd68a3f" style="width:25%;" data-name="end_date" data-type="date_picker" data-key="field_568d4bbd68a3f" data-required="1" data-width="25">
<div class="acf-label">
<label for="acf-field_568d479e68a3b-0-field_568d4bbd68a3f">End Date <span class="acf-required">*</span></label>
</div>
<div class="acf-input">
<div class="acf-date_picker acf-input-wrap" data-display_format="MM d, yy" data-first_day="0"><input id="acf-field_568d479e68a3b-0-field_568d4bbd68a3f" class="input-alt" type="hidden" name="acf[field_568d479e68a3b][0][field_568d4bbd68a3f]" value=""><input type="text" value="" class="input active hasDatepicker" id="dp1452127570219"></div>
</div>
</div>
Thanks
P.S. : I also have this on ACF's support located here.
A little late to this, but I finally figured it out.
So it turns out the .datepicker() function needs to be called on the input field with the class .hasDatepicker and not the input field with the acf id.
I have the following working:
$('.acf-field-568d4b2968a3e').find('.hasDatepicker').datepicker('option', 'minDate', minDateVar );
Hope this helps someone!
I have a form in which I have 2 fields, ssn and phone. I would like the user to enter anyone of the field. I'm using semantic validation, here is my code, can you please let me know how to validate the form using Semantic?
<form class="ui error form basic segment" role="form" method="POST" action="{{ url('/username/email') }}">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="hidden" name="_method" value="patch">
<div class="ui info message">
Please enter either SSN or phone to email you the username.
</div>
<div class="field">
<label for="ssn">SSN</label>
<div class="ui icon input">
<input type="text" class="form-control" name="ssn" value="{{ old('ssn') }}">
</div>
</div>
<div class="field">
<label for="phone">Phone</label>
<div class="ui icon input">
<input type="text" class="form-control" name="phone" value="{{ old('phone') }}">
</div>
</div>
<input type="submit" value="Email Username" class="ui primary button">
</form>
<script type="text/javascript">
$('.ui.form')
.form({
inline : true,
on: 'blur',
fields: {
username: {
identifier : 'ssn',
rules: [
{
type : 'empty',
prompt : 'Please enter a SSN'
}
]
},
}
})
;
</script>
`
Here's a little bit more elegant solution that follows Semantic UI fields identification standard.
Field could be identified not only via input[name="…"] CSS selector offered in Oniisaki's accepted answer, but also by DOM element id or data-validation attribute:
/**
* Checks whether current field value or at least one of additionally
* given fields values is not empty, neither blank string.
* #param {string} value Current field value.
* #param {string} fieldIdentifiers Comma separated field identifiers.
* #return {boolean}
*/
$.fn.form.settings.rules.allEmpty = function(value, fieldIdentifiers) {
var $form = $(this);
return !!value || fieldIdentifiers.split(',').some(function(fieldIdentifier) {
return $form.find('#' + fieldIdentifier).val() ||
$form.find('[name="' + fieldIdentifier +'"]').val() ||
$form.find('[data-validate="'+ fieldIdentifier +'"]').val();
});
};
// Using newly created custom validation rule.
// Notice how multiple fields are defined, if required.
$('.ui.form').form({
ssn: {
identifier: 'ssn',
rules: [{
// Multiple field identifiers could be defined,
// like `allEmpty[phone,email,skype]`.
type: 'allEmpty[phone]',
prompt: 'SSN or Phone (at least one field) must be filled.'
}]
}
});
I would create a Semantic UI custom validation function that accepts parameters for your purpose.
Here's the link: http://jsfiddle.net/owcfuhtq/
The code:
$(document).ready(function(){
// function to check if at least one text is not empty for a collection of elements
// text is the value of the input device
// csv is the argument as string. It's the string inside "[" and "]"
$.fn.form.settings.rules.isAllEmpty = function(text,csv){
//If the text of the field itself isn't empty, then it is valid
if (text)
return true;
var array = csv.split(','); // you're separating the string by commas
var isValid = false; // return value
$.each(array,function(index,elem){
// for each item in array, get an input element with the specified name, and check if it has any values
var element = $("input[name='"+elem+"']");
//If element is found, and it's value is not empty, then it is valid
if (element && element.val())
isValid = true;
});
return isValid;
};
var formValidationRules =
{
ssn: {
identifier: 'ssn',
rules: [{
type: "isAllEmpty[phone]",
//If you got additional fields to compare, append it inside the [] with a "," separator
//E.g. isAllEmpty[field1, field2]
prompt: 'An error occurred'
}]
}
}
$('.ui.form').form(formValidationRules);
});
If you want to include select box you can use it sth like this :
$.fn.form.settings.rules.isAllEmpty = function (text, csv) {
if (text) {
return true;
}
var array = csv.split(',');
var isValid = false;
$.each(array, function (index, elem) {
var element = $("input[name='" + elem + "']");
if (element.length == 0) {
element = $("select[name='" + elem + "']")
}
if (element && element.val()) {
isValid = true;
}
});
return isValid;
};