Special effect on parsley min check error message, Rails 4 - javascript

I am creating simple app with registration, that consists of multiple field types - string, text, check-boxes etc.
I added parsley to display errors if any. That works great.
But now I want to change color for heading when error happens - specially when parsley-min-check triggers it.
My code:
<div class="col-lg-3">
Services
<hr>
<div class="services-heading"> (Minimum*3) </div>
<div class="services-reg">
<% #services.each do |service| %>
<li>
<%= check_box_tag 'service_ids[]', service.id, false, :'data-parsley-mincheck'=>3,:required => true%>
<%= h service.name%>
</li>
<% end %>
</div>
</div>
Now I am trying to trigger script when desired div (services-reg) consists of parsley error message.
$(document).ready(function() {
if ( $( ".services-reg > li.parsley-error").length ) {
$(".services-heading > p").css("color", "red");
}
});
but something isn't working as expected.
Console don't show any error message.
Thanks in advance for your time.

You are checking if .services-reg has an li.parsley-error on your document ready. At that moment, you haven't performed any validation.
You can probably take advantage of Parsley's events, such as parsley:form:error. So you can listen to that event, that is triggered when there's a validation error.
$(document).ready(function() {
// when there's a validation error
$.listen('parsley:form:error', function(ParsleyForm) {
$(".services-heading > p").css("color", "red");
});
});
Check this jsfiddle demo, where I'm also using parsley:form:success to remove the red color, when the form is correctly validated.
UPDATE: If you have groups of divs that contain a few fields and you want to change the color of the correct div, you can use the events parsley:field:error and parsley:field:success.
Example:
$.listen('parsley:field:error', function(ParsleyField) {
var pElement = ParsleyField.$element.parent('div').prev().find('p');
pElement.css("color", "red");
});
Here I'm finding the correct div based on the jQuery element for the input that has an error. You'll probably need to tweak this, based on the DOM of your form.
Take a look at this working jsfiddle.

Related

Using a html.validationmessagefor for a client side error message

I have server side validation messages for some of my text fields. The field 'title' is a required field server side with a '[Required]' data attribute in the class, but this only seems to get checked on a postback or form submit. I'm saving the 'title' text field on a jquery .change event, sudo code below. But I want to use my validationmessagefor to show the error message from the client side check. Not sure how to go about doing this?
html.
#Html.ValidationMessageFor(model => model.Overview.Title, "", new { #class = "text-danger" })
rendered as
<span class="field-validation-valid text-danger" data-valmsg-for="Overview.Title" data-valmsg-replace="true"></span>
If I want to do some client side checking in javascript and then use this element to display a client side error message can I do so. I'm just trying to save myself of using another hidden element. I know I would have to use
data-valmsg-for="Overview.Title"
because the other data attributes are the same for all the other text fields.
Whats the best way to do display client side error messages here if I want to check to make sure the "title" has length greater then 1?
Maybe something like -
$('#Overview_Title').change(function() {
var title = $(this).val();
if (title.length == 0) {
// show error message "title has to be a value to save"
}
else {
// do other work like save to db
}
});
You've got a few ways to do this but I'd argue that this is the easiest way:
MVC will by default bundle the jquery.validate javascript library into your page. Since you are already marking the field with the [Required] attribute, the Html.EditorFor will bind the correct attributes into your HTML for you so that validation can happen as necessary.
To make your current logic work with the smallest changes, you could add a <form> tag around your input field(s). I think you need this for the validate method to work out of the box. Then your javascript would change to something like this:
$('#Overview_Title').change(function() {
if ($(this).valid()) {
// do your stuff
}
else {
// error message displayed automatically. don't need to do anything here unless you want to
}
});
This would allow you to use the Required attribute to set your error message text and your ValidationMessageFor should display the error message without any extra effort on your part.
Check out this plunkr as a proof of concept: http://plnkr.co/edit/ip04s3dOPqI9YNKRCRDZ?p=preview
EDIT
I'm not positive I understand your follow-up question. But if you wanted to add a rule to a field dynamically, you could do something along these lines:
$( "#someinput" ).rules( "add", {
required: true,
messages: {
required: "a value is required to save changes"
}
});
You could add rules that aren't reflected server side by doing something like this. Then you could validate that input in the same way.
If you want to do 100% client side validation using jquery you can use something like this:
$('#Overview_ISBN').on('input', function() {
var input=$('#Overview_Title');
var is_name=input.val();
if(is_name){input.removeClass("invalid").addClass("valid");}
else{input.removeClass("valid").addClass("invalid");}
});
Here's the code of JSFiddle link
In the example i posted , if you start typing the ISBN and the Title is empty, you will get the error message.
Not sure in your question how you want to trigger the error so i assumed it's an entry in a different input

Rails javascript; alert to fire when leaving a field

My ultimate goal is to add some validation to a set of date fields. However, my javascript sucks, so I'm starting small.
I am starting out by trying to get an alert message when a user leaves a field.
(For simplicity I'm just doing it all in my view...) Heres what I go to work...
# html.erb-template
<div class="from_date">
From Date
<input type="text" id="from_date" name="from_date"></input>
</div>
<script>
$("#from_date").blur( function() {
alert("boom!");
});
</script>
Your code seems to be fine - problem is that class and id are named the same, but you want to watch the input field not the surrounding div.
I just made a fiddle from your script and changed
the listener to be attached to the input field's id - and it's working.
the alert into a console.log
see
$("#from_date").blur(function() {.....
// instead of
$(".from_date").blur(function() {.....

Validate a value changed with Jeditable

I'm not quite good at javascript and ajax, so I ask you for help. I use Symfony2 and Twig and I have a field which I change with jediable but its value should be unique. So I check this in the controller action, but I can't succeed in making the app to act normally. I tried a lot of things and the closest to the result I want is this:
if (count($same) == 0) {
// add to database
} else {
$response = new Response();
$response->setContent('<div class="alert alert-error">
<button type="button" class="close" data-dismiss="alert">OK</button>
<strong>This value is already used!</strong> Please choose another.
</div>');
$response->send();
which outputs this nice error:
but when I click OK, the jeditable pluging is still working, and the whole error becomes editable, so the value of the input field contains all the HTML set in $response->setContent()
Because the the whole block
<div class="alert alert-error">
<button type="button" class="close" data-dismiss="alert">OK</button>
<strong>This value is already used!</strong> Please choose another.
</div>
is in the div with the class '.edit' when I click it, it becomes editable and contains this whole block. What I want is when the user clicks on the alert generated in the controller to return to input field from jeditable with a value as the original name of the category before he started to edit or with empty value.
This is my .js file but it doesn't make the input field empty (but it prints wokring) :(
$(document).ready(function(){
$('.edit').editable(path, {
cancel : 'Cancel',
submit : 'Save',
tooltip : 'Click to edit'
});
$('.bla').on('click','.alert', function(){
console.log('working');
$("input[type=text]").hmtl('');
});
});
HTML
<span class="right-spacer"><strong id="{{cat.id}}"class="edit bla">{{ cat.name }}</strong>
Any ideas for solution?
If I understand, your popup error is created dynamically when someone click on the button "Save" with an invalid value, this means that the pop-up does not exists at the $(document).ready time. This is why this part:
$('.alert').on('click', function(){
$("input[type=text]").val('');
});
Will never be executed. If you want this function to work, you will need to use delegation, as you use Jquery this will be pretty easy.
Instead of $('.alert').on('click', function(){
You will have to use something like $('body').on('click','.alert', function(){
Where body is an element that is a parent of .alert, for exemple if you know your pop-up will be created inside a div with the id of first_div(Something like <div id="first_div">) You would put instead $('#first_div').on('click','.alert', function(){
This means that the div will listen to the click events inside him, so the closer he is to the pop-up the more efficient it is.
I think this was missing,
if (count($same) == 0) {
// add to database
// clear the content on form.
//$("input[type=text]").html('');//it should be html not **hmtl**
}
Try and reply if not done..
This should do..

Custom form validation function on element with html 5

For a custom image selection tool I would like to create form validation based on html 5 form validation.
For example my form consists of the following elements:
<form class="cms-form" action="">
<table width="800">
<tr>
<td width="30%">Name:</td>
<td><input type="text" name="name" class="cms-input-text" maxlength="127" /></td>
</tr>
<tr>
<td>Image:</td>
<td><textarea name="icon" class="cms-input-file" data-file-resource="images" data-options="{"min":1,"max":3}">/location-to-image.png</textarea></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Next"/></td>
</tr>
</table>
</form>
I have a Javascript that changes the textarea (.cms-input-file) into some html to add images and hides the original textarea.
It looks something like this:
<textarea name="icon" class="cms-input-file" data-file-resource="images" data-options="{"min":1,"max":3}" style="display: none;">/location-to-image.png</textarea>
<ul class="cms-input-file-list">
<li class="cms-input-file-item" data-image="/location-to-image.png">
<img src="/location-to-thumb.png" alt="" class="cms-input-file-item-thumbnail"/>
<span class="cms-input-file-item-title">location to image</span>
</li>
<li class="cms-input-file-add">Add</li>
</ul>
Since I have allot of existing forms using html5 form validation I would like to validate this element using the default form validation within html5 supported browsers, but using a hopefully existing event.
I'm looking for something like this:
$('.cms-input-file').on('customValidateFunction', function () {
var options = $(this).data('options');
if($(this).find('> li.cms-input-file-item').length < options.min)
{
return [false, 'Add more images.'];
}
if($(this).find('> li.cms-input-file-item').length > options.max)
{
return [false, 'Remove some images.'];
}
return true;
});
Does anyone know if something like this is possible using default html 5 events or how would I go about adding this event to the submit event? To actually trigger the default browser validation look and feel.
-- edit --
So far I have made an attempt to get this result using a div element which hides the original element. But now I need to add a pattern to the element to match according to my options. Is this possible?
Current progress: http://jsfiddle.net/jeffreydev/YyEVu/
If I understand correctly what you need, I think you can achieve what you are trying to do using the pattern attribute of any input element.
I've created a very simple form in jsfiddle illustrating this.
The idea is that you update the value of your input with whatever data you have in your model when adding or removing images. The example, just adds one letter f per icon. Then, you can create a regex to match the expected valid results. In the example, pattern="f{1,3}" means that to be valid, the content can be "f", "ff", or "fff" but nothing else, which means that it'll only accept from one to three files to be sent.
You would be using just default html5 form validation, but you may need a bit of tweaking to get it working.
However, if you try this way, you should keep a couple of things in mind:
As explained in the specs, the patttern is compiled as a JavaScript regular expression with the global, ignoreCase, and multiline flags disabled
Setting the disabled property of your input so that the user can't change it would take it out of the form, and thus it won't be validated
Applying certain styles as *display:none" to the input element can cause errors when the validation fails and the browser tries to gain focus on the element.
I hope you this helps
You can install a submit handler on the <form>, and dispatch a custom event from there.
That will look something like this:
$('form.cms-form').on('submit', function(evt) {
var frm = $(this);
var allElements = $(this.elements);
$('#errors').empty();
var errors = [];
var arg = {
reportValidationError : function( msg ) {
errors.push(msg);
},
form : this
};
console.log("all elements: ", allElements);
allElements.trigger('customValidate', [ arg ]);
if( errors.length !== 0 ) {
showValidationErrors(errors);
return false;
}
return true;
});
Then, you can "hook" the customValidate event, and install your own logic...
$('textarea[name=icon]').on('customValidate', function(evt, reporter) {
var options = $(this).data('options');
// ... your validation here ...
// for example:
var txt = $(this).val();
if( txt.length < options.min || txt.length > options.max ) {
reporter.reportValidationError('error: "icon" min/max exceeded!');
}
})
Here's an example at jsFiddle.
Edit
You can style the error reporting, and tweak the code, to look and behave however you want it to. Here's an example.
A very good jquery plugin to validate your forms is Mike Alsup one's.
You will find it here: http://jquery.malsup.com/form/
It is documented, ajax compatible.
It can do serialization for one field or for all fields inside the form, so it is a big advantage regarding your problem you could need to handle fields validation and error logic with your forms.
You could add the blockUI plugin of the same author to enhance user's experience, and don't have to manage double submission of the form when javascript is enabled.
http://jquery.malsup.com/block/
Answer from 2022: Yes, it is possible without jQuery etc.
Most browsers support Constraint Validation API (even IE 11 according to "caniuse")
The recommended practice is to listen to input/submit events and then set validity flags on the input-box.
<form>
<input type="text" required id="answer">
<input type="submit">
</form>
Validation JS:
const nameInput = document.querySelector("#answer");
const form = document.querySelector("form");
function validate(e) {
if (nameInput.value == "42") { //correct!
nameInput.setCustomValidity(""); // empty means "no error"
}
else {
nameInput.setCustomValidity("Wrong answer!"); //show error text
e.preventDefault(); //prevent form submit
}
}
nameInput.addEventListener("input", validate);
form.addEventListener("submit", validate);
The input event fires even when the value is changed programmatically
P.S. Codepen to play with: https://codepen.io/jitbit/pen/XWYZjXO

Using the same JQuery tokeninput box multiple times on a page

I am using Jquery TokenInput in my rails app to help users quickly input information. Each user has a profile with many items of the same class on it, call them college_items. Each college_item has its own edit link, which pops up a modal with the appropriate edit form for the modal.
I followed Ryan Bates's screencast and got TokenInput working properly using the following code:
In application.js:
$(function() {
$("#education_major_tokens").tokenInput("/majors.json", {
theme: "facebook"
})
});
In my view:
<%= f.text_field :major_tokens %>
In my model:
def major_tokens=(ids)
self.major_ids = ids.split(",")
end
The problem I'm running into is that this same field appears in each edit form, so in the edit form for the first item everything works perfectly, but in the edit form for any other item the javascript is not initialized. My question is how can I change the javascript to initialize each time this form element appears, not just the first?
EDIT:
I thought something like this might be the solution:
$(function() {
$("#education_major_tokens").each(function(){
$(this).tokenInput("/majors.json", {
theme: "facebook"
})
});
});
but it still isn't working for me. Anyone out there have any ideas?
EDIT 2:
Figured this out finally. See my edit above, only instead of using #education_major_tokens, I set each input to have :class => "major_input" and changed "#education_major_tokens" in the code to ".major_input"
I think this is a bit late, but try to assign a class to your token field
<input class="yourtokenfield" type="text" />
After that use this
$(function() {
$(".yourtokenfield").each(function(){
$(this).tokenInput("/majors.json", {
theme: "facebook"
})
});
});
I think your problem is due to improper name for class, and remember ID must only appear once in your HTML document.

Categories