MVC Force jQuery validation on group of elements - jquery-ui

My form I am designing with MVC 4 has mutiple DIVS with many elements in each one. My objective is to open/close DIVS as the user completes the fields. However, I want to use the unobtrusive validation on each DIV, rather than the whole form. Is that possible without checking each element individually? Maybe using a DIV ID or something? I don't want to build this massive function to check each and every element in each DIV just so the user can move to the next DIV.
I am trying this and it is not working:
var elems = [];
var valid = true;
("#Contact").find('.text_input').each(function() {
elems.push(this.id);
}
for (var i = 0; i<= elems.length; i++) {
if ($("#" + elems[i]) != undefined) {
$("#form1").validate().element("#" + elems[i]))
if ($("#" + elems[i]).valid()) {
}
else {
valid = false;
}
}
}
but I keep getting an undefined error. The elements in the DIV that have the class text_input are the ones with validation required.

You can validate individual controls using Validator.element(element) - see documentation here, so you could use the following approach (you haven't posted the views html so can't write the actual code for you)
In the Next button click event
Select all the the controls within the
associated div - e.g. var controls = $(this).closest('div').find('input, textarea, select');
In an $.each loop, call $("form").validate().element($(this));
If necessary, test if valid with $(this).valid();
If everything is valid, hide the current div and display the next
Edit (example added)
View
<div class="section">
<h2>Section 1</h2>
.... // Your inputs and validation
#Html.LabelFor(m => m.SomeProperty)
#Html.TextBoxFor(m => m.SomeProperty)
#Html.ValidationMessageFor(m => m.SomeProperty)
<div class="error"></div>
<button type="button" class="next">Next</button>
</div>
<div class="section">
<h2>Section 2</h2>
.... // Your inputs and validation
<div class="error"></div>
<button type="button" class="next">Next</button>
</div>
<div class="section">
<h2>Section 3</h2>
.... // Your inputs and validation
<div class="error"></div>
<button type="submit" class="next">Submit</button> // submit button for last section
</div>
CSS
.section:not(:first-of-type) {
display:none;
}
Script
$('button').click(function () {
var container = $(this).closest('.section');
var isValid = true;
$.each(container.find('input'), function () {
$('form').validate().element($(this));
if (!$(this).valid()) {
isValid = false;
return false;
}
});
if (isValid) {
container.next('.section').show().find('input').first().focus();
container.hide();
} else {
container.find('.error').text('please complete');
}
});

Related

I want to display label text for particular record in for loop

<div ngFor="let data of Requests">
FirstName:<b>{{data.name}}</b>
<button (click)="AcceptRequest()">Accept</button>
<button (click)="CancelRequest()">Decline</button>
<label>{{RequesStatus}}</label>
I want to display a label on accepting or declining requests for that request only in my code it displays for every request.
Try this, this should work:
<div *ngFor="let item of requests; index as ix">
ix: {{ix}} FirstName:<b>{{item.name}}</b>
<button (click)="HandleRequest(true, ix)">Accept</button>
<button (click)="HandleRequest(false, ix)">Decline</button>
<label>{{requesStatus[ix]}}</label>
<!-- or -->
<label>{{(isAccepted[ix]) ? 'accepted' : 'declined'}}</label>
</div>
In TS
// in class level declare this
requesStatus: string[] = [];
// or
isAccepted: boolean[] = [];
// function to set and use in template
HandleRequest(accepted, ix) {
this.requesStatus[ix] = (accepted) ? 'accepted' : 'declined';
// or
this.isAccepted[ix] = accepted;
}

JQuery Mobile filterable listview with multiple filters

I have a JQM 1.4.2 filterable listview which contain entries in different languages.
I would like to search only within items code, not the whole description, whereby i set the data-filtertext for list items to the item code, e.g. "Apple" or "Banana".
This works ok but now i need an additional language filter, e.g. "EN", "DE", and so on:
...
<li data-filtertext="Apple language_en">
<h2>Title</h2>
<p>Red fruit</p>
<p class="ui-li-aside"><strong>EN</strong></p>
</li>
...
...
<li data-filtertext="Banana language_de">
<h2>Titel</h2>
<p>Beschreibung</p>
<p class="ui-li-aside"><strong>DE</strong></p>
</li>
...
This is my data input:
<form class="ui-filterable">
<div class="ui-grid-a">
<div class="ui-block-a">
<input id="descriptions-input" data-type="search" placeholder="Search..." />
</div>
<div class="ui-block-b">
<fieldset data-role="controlgroup" data-type="horizontal">
<input name="lang-en" id="lang-en" type="checkbox" data-mini="true">
<label for="lang-en">EN</label>
<input name="lang-de" id="lang-de" type="checkbox" data-mini="true">
<label for="lang-de">DE</label>
<input name="lang-fr" id="lang-fr" type="checkbox" data-mini="true">
<label for="lang-fr">FR</label>
</fieldset>
</div>
</div>
</form>
What i try to do now, is that when a checkbox is selected, only the list items belonging to that language are visible.
How can i set this additional filter to my filterable jQuery Mobile listview?
Plunker: http://plnkr.co/edit/TV6rcatzdvaIvQzWBdoI?p=preview
EDIT:
This is the final solution, thanks to EZANKER: https://jsfiddle.net/m64kg5fw/4/
The filterable widget as a filterCallback property: http://api.jquerymobile.com/filterable/#option-filterCallback
You can use this to write a function that checks both the text and which language checkboxes are checked.
$(document).on("pagecreate", "#list-descriptions", function () {
$("#descriptions-list").filterable('option', 'filterCallback', checkedOrMatch);
$("#searchLangs input").on("change", function(){
$("#descriptions-list").filterable("refresh");
});
});
function checkedOrMatch(idx, searchValue) {
var ret = false;
var en = $("#lang-en").is(':checked');
var de = $("#lang-de").is(':checked');
var fr = $("#lang-fr").is(':checked');
var ignoreLang = false;
if (!en && !de && !fr) {
ignoreLang = true;
}
if (searchValue && searchValue.length > 0) {
searchValue = searchValue.toLowerCase();
var filttext = $(this).data("filtertext") || '';
filttext = filttext.toLowerCase();
if (filttext.indexOf(searchValue) < 0) {
ret = true; //filter this one out
} else if (!ignoreLang) {
//found filter text now check language
if ( (filttext.indexOf("language_en") > 0 && !en) || (filttext.indexOf("language_de") > 0 && !de) || (filttext.indexOf("language_fr") > 0 && !fr) ) {
ret = true; //filter this one out
}
}
}
return ret;
}
Updated DEMO
The checkedOrMatch functions runs for each item in the list. It first tests if the entered search text is found in the filter text. If it is, it then sees which language buttons are checked and tests the item for that language. I also added code to re-trigger the filter if the user selects language buttons after typing the search criteria.
NOTE: if the user types in "lang" you might not get what you want... In that case you could move the language designation out of the filter text and into a separate data-attribute.

Fire validation of asp.net razor view page input controls on kendo ui upload select file button

I have an asp.net mvc application with Kendo UI controls. I have an upload file razor view with few input controls on the page.
My requirement is to fire the page validation on the file select button for all the other input controls in the page. (at least required validation has to get fired)
I can have a submit button and fire the validation. But I need to have that functionality on the Kendo UI upload select button. i.e,User can select / browse file to upload only after filling valid values for all the input controls.
I have done many searches and trial and error methods in my code but nothing helped.
I am new to Kendo UI controls so please help
Thanks in advance,
I am attaching sample code below:
#{
ViewBag.Title = "Kendo Validate";
}
#model KendoInputs_Validation.Models.ViewModel
#using(Html.BeginForm())
{
<div id="tickets">
<h3>Book Tickets</h3>
<ul id="innerList">
<li>
#Html.LabelFor(m => m.ComboBox)
#Html.Kendo().ComboBoxFor(m => m.ComboBox)
#Html.ValidationMessageFor(m => m.ComboBox)
</li>
<li>
#Html.LabelFor(m => m.DropDownList)
#(Html.Kendo().DropDownListFor(m => m.DropDownList)
.OptionLabel("Select item...")
.BindTo(new SelectList(new string[] { "Item1", "Item2", "Item3" }))
)
#Html.ValidationMessageFor(m => m.DropDownList)
</li>
<li>
#Html.LabelFor(m => m.DatePicker)
#Html.Kendo().DatePickerFor(m => m.DatePicker)
#Html.ValidationMessageFor(m => m.DatePicker)
</li>
<li>
#Html.LabelFor(m => m.Number)
#Html.Kendo().NumericTextBoxFor(m => m.Number)
#Html.ValidationMessageFor(m => m.Number)
</li>
<li class="accept">
<button class="k-button" type="submit">Submit</button>
</li>
<li>
#(Html.Kendo().Upload()
.Name("files")
.Messages(msg => msg
.Select("Browse")
))
</li>
</ul>
</div>
}
<script>
$(document).ready(function () {
/* Bind Mutation Events */
var elements = $("#tickets").find("[data-role=combobox],[data-role=dropdownlist],[data-role=numerictextbox],[data-role^=date], [data-role^=upload]");
//correct mutation event detection
var hasMutationEvents = ("MutationEvent" in window),
MutationObserver = window.WebKitMutationObserver || window.MutationObserver;
if (MutationObserver) {
var observer = new MutationObserver(function (mutations) {
var idx = 0,
mutation,
length = mutations.length;
for (; idx < length; idx++) {
mutation = mutations[idx];
if (mutation.attributeName === "class") {
updateCssOnPropertyChange(mutation);
}
}
}),
config = { attributes: true, childList: false, characterData: false };
elements.each(function () {
observer.observe(this, config);
});
} else if (hasMutationEvents) {
elements.bind("DOMAttrModified", updateCssOnPropertyChange);
} else {
elements.each(function () {
this.attachEvent("onpropertychange", updateCssOnPropertyChange);
});
}
});
function updateCssOnPropertyChange (e) {
var element = $(e.target);
element.siblings("span.k-dropdown-wrap")
.add(element.parent("span.k-numeric-wrap"))
.add(element.parent("span.k-picker-wrap"))
.toggleClass("k-invalid", element.hasClass("input-validation-error"));
}
</script>
<style type="text/css">
.k-widget > span.k-invalid,
input.k-invalid
{
background: red;
}
#innerList li
{
margin: 10px 10px;
}
</style>
Edit:- I can write an Select event for the upload control as below:
#(Html.Kendo().Upload()
.Name("files")
.Events(events => events
.Select("onSelect")
)
)
But in this case user has to select a file for getting the validation errors.
Our requirement is that when user clicks the select button validation errors should pop up. if no errors then only file select window opens.
Thanks
You can bind a click function to your upload during initialization and check your custom vale before the default behavior, the browse fro dialog, window is invoked.
$(document).ready(function () {
$("#yourUploadName").click(function (e) {
var valid=myValidationFunction();
if (!valid) {
alert("Bad");
//This will cancel the showing of the search dialog
e.preventDefault();
}
});
});

How to prevent saving of duplicate data?

I am developing MVC app.
I am using Jquery in Creat-Veiw for validate the data.
I am adding the Role and checking whether that Role(or you can say UserName) already exists in DB or not.
If Role already exists then validation message should display and should not be allow to add in db (should not allow to save).
I have a text-box which accepts the Role, on the blur function I have checked whether Role already exists or not.
Every thing working ok, If Role already exists then validation message comes up.
But after clicking on save button it saves in db.
I want to prevent it ? How to do this ?
I have below code of Create View.
#model IEnumerable<PaymentAdviceEntity.Role>
<div id="roleList">
<div class="span6">
<div class="span12 HeaderField2">
Roles
<legend style="margin-bottom:2px;margin-top:5px;"></legend>
</div>
<div class="span12">
<div style="display:inline-block"></div>
<div id="addrole" style="display:none">
<span> #Html.TextBox("RoleName", String.Empty, new { #id = "RoleName",style="margin-bottom:0px;" })</span>
<span>
<input type="button" value="Save" id="btnSave"/>
<input type="button" value="Cancel" id="btnCancel" />
</span>
</div>
<div style="margin-top:5px;">
<span id="RoleNameValidation" style="display:none;color:Red;">Role already exists</span>
</div>
</div>
</div>
For this I am using the below Jquery.
$("#RoleName").blur(function ()
{
var Role_Name = $('#RoleName').val();
//alert(RoleName);
var url = "#Html.Raw(Url.Action("checkForUniqueName","Role",new {#RName = "RoleName"}))";
url = url.replace("RoleName", Role_Name);
$.post(url, function (data)
{
if (data == false) {
$("#RoleNameValidation").show();
$('#RoleName').focus();
}
else {
$("#RoleNameValidation").hide()
}
});
});
and the controller Code is....
public ActionResult checkForUniqueName(string RName)
{
bool Valid = false;
var RoleList = from e in db.Roles
where e.Name.Equals(RName)
select e;
if (RoleList.Count() > 0 )
{
Valid = false;
}
else
{
Valid = true;
}
return Json(Valid, JsonRequestBehavior.AllowGet);
}
You can use validation for this purpose if you don't want to insert duplicate records in database.
Try to create a custom rule using the jQuery Validate plugin (using addMethod) that checks if the role is already exists in database.You can find good help at http://matthewmuro.com/2012/05/08/adding-custom-jquery-validation-to-your-form/

Dart - second time click event detect

var modify = document.queryAll("#tab");
for(var i=0; i<modify.length; i++)
{
modify[i].on.click.add((Event e) => show_content(i));
}
// code for hide_content()
i have two function show_content() and hide_content() that operates on the div's
i'm not able to detect second time click on a div to trigger hide_content(). i've tried with a semaphore and - no luck
<div id="tab"> </div>
<div id="content"> </div>
<div id="tab"> </div>
<div id="content"> </div>
queryAll is used for non-unique elements. Using queryAll for an unique element with the ID tab doesn't make any sense. You should use query('#tab') where you get just a single DivElement as its return value.
However I'm not sure, I undersand your problem but if you need a toggle button, you're maybe looking for something like this:
DivElement uniqeDiv;
void toggle() {
if(uniqeDiv.hidden) {
// uniqeDiv.hidden = false;
show();
} else {
// uniqeDiv.hidden = true;
hide();
}
}
void main() {
uniqeDiv = query('#tab');
uniqeDiv.on.click.add((Event e) => toggle());
}

Resources