jQuery Validation not working with jQuery Text Editor Plugin (TextArea) - jquery-validate

I am working with the jQuery TE plugin (http://jqueryte.com/). It does not seem to work with the jQuery Validation plugin.
A regular textarea works fine but if I want to transform it into a jqte WYSIWYG I lose that functionality.
In this example the Name and Bio fields are validated, but not the Resume field.
jsFiddle
Html:
<form id="frmExample">
<div><b>Name:</b></div>
<input name="txtName" id="txtName" class="required" />
<br />
<div><b>Bio:</b></div>
<textarea cols="40" rows="6" name="txtBio" id="txtBio" class="required"></textarea>
<br />
<div><b>Resume</b></div>
<textarea name="txtResume" class="required" id="txtResume"></textarea>
<br />
<br />
<input type="submit" value="Save" />
JS:
$("#txtResume").jqte();
$("#frmExample").validate();

I have detailed an example of this in a blog post: http://chadkuehn.com/jquery-te-validation/
When you place a jqte on a TEXTAREA tag it hides the original element. So in the validation plugin you must adjust the markup that's visible when highlighting and unhighlighting. You must also do some adjusting to the placement of the error label.
errorPlacement: function (error, element) {
var el = $(element).closest(".jqte");
if (el.length == 1) {
error.insertAfter(el);
} else {
error.insertAfter(element);
}
},
highlight: function (element, errorClass, validClass) {
$(element).addClass(errorClass).removeClass(validClass);
var el = $(element).closest(".jqte");
if (el.length == 1) {
el.addClass(errorClass);
}
},
unhighlight: function (element, errorClass, validClass) {
$(element).removeClass(errorClass).addClass(validClass);
var el = $(element).closest(".jqte");
if (el.length == 1) {
el.removeClass(errorClass);
}
}
View a DEMO here.

Using ASP.NET MVC I would recommend this...
To have jQuery validation automatically with jqte, execute at startup:
$('.jqte_editor').change(function () {
if ($(this).parent().siblings('.textarea-editor').hasClass('.input-validation-error'))
$(this).parent().addClass('input-validation-error');
else
$(this).parent().removeClass('input-validation-error');
});
$('form').bind('submit', function () {
$('.textarea-editor.input-validation-error').parent().parent().addClass('input-validation-error');
$('.textarea-editor:not(.input-validation-error)').parent().parent().removeClass('input-validation-error');
});
And remember to put "textarea-editor" class in the textarea

Related

Durandal widget does not update value in parent view model

I'm using Durandal with the observable plugin enabled to utilize ES5 getters and setters. I've created a simple widget that takes a value and binds it to a text box:
Here's the widget's viewmodel.js:
define([], function () {
var ctor = function () {
this.activate = function (settings) {
this.value = settings.value;
}
};
return ctor;
});
And here's the widget's view.html:
<span>
This textbox is in the widget:
<br />
<input type="text" data-bind="value: value" />
</span>
When using the widget, if the value is passed in as a ko.observable, then everything works as expected. However, if I use the ES5 getter/setter method provided by the observable plugin, modifying the value in the widget does not cause the parent view model to be updated. Modifying the value in the parent view does update the widget though:
define(['durandal/app', 'knockout'], function (app, ko) {
var ctor = function () {
this.value = ko.observable('Test'); // This works as expected
this.value = 'Test'; // This does not work
};
return ctor;
});
Here's the parent view:
<section>
<h1>Widget Test</h1>
This textbox is not in the widget:
<br />
<input type="text" data-bind="value: value" />
<br /><br />
<div data-bind="widget: { kind: 'testWidget', value: value }"></div>
</section>
Am I doing something wrong that is preventing the value from being pushed back to the parent view model?
You will have to define/use a observable property to make it two-way binding so that the changes made in view will be reflected in your View Model.
this.value = ko.observable('Test'); works for your requirement.

Prevent knockout validation from evaluating on initial load

I have a simple view-model with a few required attributes... I want each input to highlight red if the corresponding property is not valid, but I don't want this highlighting to display when the page is initially loaded... only when a value changes or when the user tries to save / continue...
Right now it's validating the view-model on initial load because I'm specifying data-bind="css: { error: name.isValid() == false }", but I don't know of any other way to get this to work dynamically (similar to how jQuery unobtrusive validation works)...
var foo = { name: ko.observable().extend({required: true}) };
<div data-bind="css: { error: !name.isValid() }">
<input type="text" data-bind="value: name" />
</div>
Any ideas on how to make this work would be appreciated... Thanks!
A better approach is to configure knockout validation to decorate the element with the validationElement class. This is done by adding this configuration option:
ko.validation.configure({ decorateElement: true });
Click here to see a jsfiddle demonstrating this.
****EDIT, IN RESPONSE TO COMMENT FROM QUESTION ASKER***
If you need to decorate the parent element, a more elegant and reusable solution is to apply this custom binding to the parent element.
Javascript
ko.bindingHandlers.parentvalElement = {
update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var valueIsValid = valueAccessor().isValid();
if(!valueIsValid && viewModel.isAnyMessageShown()) {
$(element).addClass("parentError");
}
else {
$(element).removeClass("parentError");
}
}
};
And apply the binding in your HTML like so:
<form data-bind='submit:OnSubmit'>
<label data-bind='parentvalElement:name'>
<span>Name</span>
<input data-bind="value: name" />
</label>
<input type='submit' value='submit' />
<form>
Take a look at this updated jsfiddle to see it in action.
So, here is the solution I came up with:
var Foo = function()
{
this.name = ko.observable().extend({required: true}).isModified(false);
this.validate: function()
{
if (!this.isValid())
{
//... loop through all validated properties and set .isModified(true)
return false;
}
return true;
};
ko.validation.group(foo);
};
var Bar = function()
{
this.foo = new Foo();
this.errors = ko.observableArray([]); //<-- displays errors for entire page
this.save = function()
{
if (!this.foo.validate())
{
this.errors(ko.toJS(this.foo.errors()));
}
};
}
ko.applyBindings(new Bar());
And here is the markup...
<div data-bind="with: foo">
<div class="control-group"
data-bind="css: { error: name.isModified() && !name.isValid() }">
<label class="control-label">Name<span class="help-inline">*</span></label>
<div class="controls">
<input type="text" class="input-block-level" placeholder="Name"
data-bind="value: name, event: { blur: function () { name.isModified(true); }}" />
</div>
</div>
<div class="alert alert-error"
data-bind="visible: $parent.errors().length > 0">
<h5>Errors!</h5>
<ul data-bind="foreach: $parent.errors()">
<li data-bind="text: $data"></li>
</ul>
</div>
</div>
<button type="submit" class="btn btn-primary" data-bind="click: save">Save</button>
and here is the CSS
.error { color: Red; font-weight: bold; }
.help-inline { display: none; }
.error .help-inline { display: inline-block; }
.error input { border-color: Red; }

.on('click') with ajax content from another ajax content

Trying to get an event triggered with ajax content whose parent elements were also ajax loaded.
<div id="content"><!-- NOT ajax-loaded -->
<div id="location"> <!-- #location IS ajax-loaded -->
<div id="add_location> <!-- #add_location IS ajax-loaded from a #location event -->
<input type="text" id="add_location_city_example" />
<input type="text" id="add_location_state_example" />
<input type="submit" id="add_location_confirm" />
</div>
</div>
</div>
$(function(){
$('#content').on('click', '#add_location_confirm', function(){
console.log('debug 1');
add_location();
// will not be called
});
$('#location').on('click', '#add_location_confirm', function() {
console.log('debug 2');
// will not be called either
add_location();
});
});
If I have onclick="add_location()" and function add_location() { console.log('debug 3); } in my .js then it will obviously be called BUT I then cannot get $('#add_location_city_example').val() because none of it will be in the dom.
NOTE: using 1.9.1
I've been using this for a while, makes it much easier to handle situations like you are describing + there is only one even assignment for pretty much all clicks on the page, including elements that will appear on the page in the future:
$(document).bind('click', function (e) {
var target = $(e.target);
if (target.is('#content')) {
e.preventDefault();
// do whatever
} else if (target.is('#location')) {
e.preventDefault();
// do whatever else
}
});
or in your case it would probably be more like this:
$(document).bind('click', function (e) {
var target = $(e.target);
if (target.is('#add_location_confirm')) {
e.preventDefault();
if (target.closest('#location').length == 0) { // not yet have location injected via ajax
// do something
} else {
// location has been injected, do something else
}
});

knockout wizard + Jquery

I have a wizard contains 4 step with knockout its work fine but when i added datepicker of Jquery on step 2 date picker doesn't display (just an input type text display) if i refresh my browser it display, but i lose information of step 1 (if i refresh my browser), how can i solve my problem,
my wizard its like this: http://jsfiddle.net/FyuSD/36/
wizard.cshtml:
....
<script id="step1" type="text/html">
<div>Name: <input type="text" data-bind="value: Name"></div>
<div>Description: <input type="text" data-bind="value: Description"></div>
</script>
<script id="step2" type="text/html">
Start: <br/><input type="text" id="from" data-bind="value: StartDate">
Stop:<br/> <input type="text" id="to" class="required" data-bind="value: EndDate">
</script>
.....
DatePicker.js:
$(function () {
$("#from").datepicker({
showOn: "button",
buttonImage: "/Content/images/calendar.gif",
buttonImageOnly: true,
defaultDate: "+1w",
changeMonth: true,
numberOfMonths: 1,
onSelect: function (selectedDate) {
$("#to").datepicker("option", "minDate", selectedDate);
}
});
$("#to").datepicker({
showOn: "button",
buttonImage: "/Content/images/calendar.gif",
buttonImageOnly: true,
defaultDate: "+1w",
changeMonth: true,
numberOfMonths: 1,
onSelect: function (selectedDate) {
$("#from").datepicker("option", "maxDate", selectedDate);
}
});
});
I'm sorry for my bad English
thanks,
I played with the fiddle a bit and your solution is the answer to this question
jQuery UI datepicker change event not caught by KnockoutJS
Which shows a datepicker implementation for custom bindings as described in the knockout documentation: Knockout - Custom Bindings
You need to create a custom binding handler that will initialize your datepickers when the template is rendered.
// call this before you call ko.applyBindings()
ko.bindingHandlers.datepicker = {
init: function(element, valueAccessor, allBindingsAccessor) {
// initialize here
},
update: function(element, valueAccessor, allBindingsAccessor) {
// change handler here
}
};
When you declare your data bindings use the name of your custom binding (instead of "value: StartDate")
<br/>
Start :<input type="text" id="from" data-bind="datepicker: StartDate, datepickerOptions: {onSelect: $root.onSelectStartDate()}" />
<br/>
End :<input type="text" id="to" data-bind="datepicker: EndDate, datepickerOptions: {onSelect: $root.onSelectEndDate()}" />
Of course $root refers to your ViewModel class so that means you need some methods there. This is where you could put your minDate and maxDate code.
function ViewModel() {
// ...
self.onSelectStartDate = function() {
return function() {
alert("Start Date selected");
};
};
self.onSelectEndDate = function() {
return function() {
alert("End Date selected");
};
};
};
I tested it in an updated fiddle here http://jsfiddle.net/carbontax/bwA4N/5/. It looks funny because the datepicker css is not available, but the binding handler is doing the right thing.

Using Validation Plugin, how can i submit form when either one of the checkbox is checked or specific text field is not empty

//Using Validation Plugin, how can i submit form when either one of the checkbox is checked or specific text field is not empty? I have checkboxes which generates dynamically and category_name text field. I want to submit form when either one of the checkbox is checked or category_name text field is not empty...
<?php
while($cat_row = "fetch_result"){
$tr.='<b><input type="checkbox" class="required" name="category[]" value="'.$cat_row['category_name'].'" id="category[]" checked/>'.$cat_row['category_name'].'</b>';
}
?>
//HTML File
<body>
<form id="abc" name="abc" action="PATH_TO_PHPFILE" method="post" enctype="multipart/form-data" >
<div id="cd">
<?=$tr?>
<div id="err"></div>
</div>
<input type="text" name="category_name" id="category_name" class="text_box" value="" />
</form>
<script>
$(function() {
$("form").validate({
rules:{
category:{
required:true,
minlength:2
}
},
errorPlacement: function(error, element) {
error.appendTo('#err');
},
submitHandler: function(form){
var options = {
success:function (data){
$.unblockUI();
//do something
},
beforeSubmit:function (){
//do something
}
};
$(form).ajaxSubmit(options);
}
});
});
</script>
</body>

Resources