knockout js: The "with" binding breaks the jquery ui - jquery-ui

http://jsfiddle.net/AYPze/9/
In this example I have two similar divs with the same goal. Bind the selected date from the datetimepicker and save it to the object binded by knockout js.
The problem with the first div is that the datetimepicker won't show up because i use the knockout "with" binding.
The second div uses the normal knockout js binding syntax, which works fine with the datetimepicker.
I experienced this behavior also with the jquery-ui Accordion
My Questions:
Is this a bug in knockout or jquery-ui?
Is there a work around, so I can use the "with" binding?

Your problem is related to the with binding, but not in the way you think.
The problem you have is that the with binding in this case will remove the jQuery datepicker from the DOM element and that is why you don't see the datepicker for the first textbox.
The main problem here is that you are breaking a very important rule when working with Knockout and the DOM. You shouldn't access the DOM directly with jQuery like you are doing now. You have to use a bindingHandler to bridge the gap between your data model and the DOM model.
The Binding Handlers seem complex at first, but they are pretty handy once you get to know them.
Here is an updated version of your fiddle with a working datepicker: http://jsfiddle.net/AYPze/10/

Related

Issue with jQuery autocomplete 1.9.2 and knockout

I've been using this knockout binding from this jsfiddle (from this initial SO question) for a while and it has been working.
After upgrading to jQuery 1.8.3 and jQuery UI 1.9.2 (jsfiddle), when typing text into the input, after the items list is populated (but not selected!), the input textbox is cleared and you have to restart typing from the beginning. That's annoying as you won't be able to complete your text input because you always have to start from scratch.
If the jqAutoSourceInputValue and the jqAutoSourceValue have the same property name, it works, but then either the id or the input value after the selection are not the desired one.
Looks like the issue is coming from the fact that the binding's update function has a dependency on the observableArray that is being updated. I am not quite sure what has changed in jQuery UI to make the actual behavior change from before, but one fix is to update to Knockout 2.2.1 and access the observableArray via the peek function to avoid a dependency. Something like:
var source = (ko.isObservable(allBindings.jqAutoSource) ? allBindings.jqAutoSource.peek() : allBindings.jqAutoSource) || [];
Updated fiddle: http://jsfiddle.net/rniemeyer/xXuq6/
If you can't update to KO 2.2.1, then there are some other ways to do it as well. Let me know.

making unobtrusive validation work when using Select2 ASP.NET MVC

Select boxes converted to Select2, do not automatically integrate with unobtrusive validation mechanism in ASP.NET MVC framework.
For example, on a form which contains a regular select box (marked as required in model definition), submitting the form while no options have been selected in the select box, will cause the border and background of the select box to take a reddish color, and by using #Html.ValidationMessageFor, error messages, if any, can be displayed beside the box. However if the select box is converted to a Select2 component, then none of the mentioned features work any more. Even the validation error message will not show up.
It seems that the reason for even the validation error message not showing, is because Select2 changes the display CSS property of the original select box to none (display:none), and I guess the unobtrusive validation script does not bother generating error messages for invisible fields.
Any ideas / solutions?
This issue isn't really specific to Select2, but rather to the jQuery unobtrusive validator.
You can turn on validation for hidden fields as highlighted in this answer.
$.validator.setDefaults({
ignore: ''
});
As the comments noted, it didn't work inside an anonymous callback function within $(document).ready(). I had to put it at the top level.
I've run into similar issues with the select2 plugin. I don't know exactly which features you're using specifically, but in my experience, when you set an element as a select2 in the document.ready event, the plugin will change some of the element's attributes on the fly (inspect one of the elements after your page has finished loading - oftentimes you'll see the id and class properties are different than what you're seeing when you view source).
It's difficult to offer more without actually seeing the code, but here's a few ideas to get you started:
First off, obviously make sure you have the a link to your select2.css stylesheet in the header.
Then, since you're talking about form submissions, I'd recommend you examine whether or not you're getting a full postback or submitting via AJAX (if you're using jQueryMobile, you're using AJAX unless you override it in the jquerymobile.js file or set a data-ajax="false" in your form attributes). You can just look at the value returned by Request.IsAjaxRequest() for this. Obviously if you're submitting via ajax, you won't hit the document.ready event and the select2 won't initialize properly and you'd need to figure out a way around that. Try refreshing the page after the submit and see if it renders the select2 component.
Then I'd suggest examining the elements and see if they're not behaving like you'd expect because you're actually trying to work with classes that the plugin has reassigned at runtime. You can either just adjust your logic, or you can dig into the select2 code itself and change the behavior - it's actually fairly well-documented what the code is doing, and if you hop on the Google group for select2, Igor is usually pretty quick to follow up with questions.
like this
$('select').on('select2:select', function (evt){
$(this).blur();
});
$('body').on('change', 'select.m-select2', function () {
$(this).blur();
})

How to bind backbone.js events to JQuery UI dialogue windows?

I'm very new to backbone.js but we're starting to use more and more JS on the front end and I wanted to use some framework to give the code structure - backbone seems to suit our needs.
So started off with a very simple test app that launches a dialogue window using jquery-ui. The problem I have is that since jquery-ui adds a wrapper DIV round the original template used by backbone, the events no longer fire.
I don't want to use the jquery-ui event model as I'd rather just use the one - how can I bind backbone's to this new structure?
It looks as though the call to _.template() is actually doing the wrapping in an extra div. The parent div with the events bound to it is being left behind appended to #well. A simple workaround is to call .parent() on the result of getting the element with the model class ID. See here for example
There's more than likely some information in the _ documentation that might shed some more light on the problem too.
OK - at the end of this project, I finally realised that I hadn't answered this. What happens is when you create a .dialog with JQueryUI, it actually detatches your original DOM element and moves it to the bottom of the DOM wrapped in it's own JQueryUI markup to turn it into a dialog.
Since the Backbone view's element has now been moved, Backbone doesn't pick up any events that fire as it's happening outside it's own "view" as far as it is concerned.
So what you have to do is reassign the view's element:
var dlg = this.$("#dialogue-properties").dialog({ ..});
this.setElement(dlg);
Where this is the view. This is done within the initialize method
You can create div wrapper in your view and modal it's content, as described here (first part of the post)
cocovan does a good job explaining the problem in his answer. However, as for the solution, the JQuery UI team actually added a method at the end of 2012 (Allow dialog to be attached to a element other than body) that takes care of this issue.
It is the appendTo(selector) method (jQuery Dialog appendTo method). So simply specify to which element you want the dialog appended.

My dropdown is not showing the data

I am having a html dropdown
<select id="ExternalIp" onchange="externalIpchange()"></select>
I bind the data to dropdown through jquery and a I am passing data from controller which is working properly. I want to change the look and feel of the dropdown so I called a function
$("#ExternalIp").selectbox();
Now the look and feel of drop down is changed but it is not showing the data which I bind to dropdown. I am not getting what is the problem. Plz help
It appears as if the jQuery plugin you are using resets the values bound to the select list.
Look for a method provided within your jQuery plugin to rebind the data which you earlier attached with jQuery or style your element first and then try binding the values.
Cheers!!!

Why does jQuery UI's datepicker break with a dynamic DOM?

I'm working with a dynamic DOM here, and have called the jQuery UI datepicker to all inputs with a specific class name, in this case .date
It works great with the first, static, construct but when I clone it the event handlers don't seem to want to move over. I get the Firebug error:
inst is undefined
I tried looking into jQuery's new live() function but couldn't combine the two. Any ideas?
Ah, got it. Right after I append the HTML to the DOM I run this on all the inputs I'd like to have a datepicker pop up with. Datepicker adds a class to elements it has been attached to, so we can filter out existing inputs and only apply it to new ones.
$('.date').not('.hasDatePicker').datepicker();
I hope this helps people as I was Googling for days and didn't find anything!
You should also note that it would be faster to check for input.date in the new generated HTML by setting that as a context, rather than the whole page, as it will save time, due to this being a more efficient operation.
I had a similar Issue, I had multiple tables on a page and each had multiple datepickers, also on click of button "AddLine" it added a table row with dynamic HTML and datepicker.
I realized after a lot of search that my input date fields had no "id" defined they looked like this
<input type="text" class="datepicker" name="mDate1" value="" size=8 >
jquery was pointing all the date fields values to the very first date field defined on page, the calendar would popup on all the date fields but the value of 1st date field would change, I made a change to the html like this
<input type="text" class="datepicker" id="Date1" name="mDate1" value="" size=8 >
by adding a "id" and it started working, for the dynamic date fields I change the Id like this
var allColumns = $("#"+$tableId+" tr:last td");
$(allColumns).each(function (i,val) {
if($(val).find(":input").hasClass("datepicker")){
$(val).find(":input").attr("id",newId+$(val).find(":input").attr("id"));
}
});
You need to use the 'live' event to make it work with dynamic DOM. So, if the class for your datepicker inputs is 'date-input', following code will make it work:
$(document).ready(function() {
$('.date-input').live('click', function() {
$(this).datepicker('destroy').datepicker({showOn:'focus'}).focus();
});
});
This might be a little late, but all the suggestions above didn't work for me, I came up with an easy solution for this.
First, what is causing the problem:
JQuery assign datepicker to element id. if you are cloning element, then same id might be cloned as well. which jQuery doesn't like. You might end up with either receiving null reference error or the date being assigned to first input field regardless which input field you click on.
Solution:
1) destroy datepicker
2) assign new unique ids to all input field
3) assign datepicker for each input
Make sure your input is something like this
<input type="text" name="ndate[]" id="date1" class="n1datepicker">
Before you clone, destroy datepicker
$('.n1datepicker').datepicker('destroy');
After you clone, add these lines as well
var i = 0;
$('.n1datepicker').each(function () {
$(this).attr("id",'date' + i).datepicker();
i++;
});
and the magic happens
Use
$j(id or class).removeClass('hasDatepicker').datepicker();
It is working
Use jQuery selectors:
$(".mydatepicker:not(.hasDatepicker)").datepicker()
Multiple instances of the jquery-ui library on the page will cause this error too. Removing redundant instances work for my case
I experienced the same symptom, in this caused by having a td containing element with the same id attribute as the input,
<td id="fld_xyz"><input id="fld_xyz" class="date" /></td>
I know this isn't ideal anyway, but it's worth knowing that the datepicker component seems to be relying on the uniqueness of the id.
I had this problem. My situation ended up being I had another element with the same ID as the input with the datepicker.
Today I faced the same issue... I am using datetimepicker plugin in my application.
Also using jquery's default datepicker too. When ever I am invoking them both on document ready I am getting the error inst is undefined.
$(document).ready(function(){
$(".datepickerCustom").datetimepicker();
$(".datepicker").datepicker();
$("#MainForm").validationEngine('attach');
....
});
So I changed the code to invoke before document ready like below:
$(".datepickerCustom").datetimepicker();
$(".datepicker").datepicker();
$(document).ready(function(){
$("#MainForm").validationEngine('attach');
....
});
Now every thing is working fine. No problems.
I had a similar problem with data picker not working after a first call. I found an answer to my issue here:
http://www.stemkoski.com/problem-with-jquery-ui-datepicker-dynamic-dom/
I was cloning sections dynamically from template and inadvertently including the class that datepicker adds once its called:
hasDatepicker
I placed my first datepicker call after I clone the template and that did it. I then added a datepicker call after each instance of clone:
$(source).clone().appendTo(destination).find(".datepicker").datepicker();
After trying many of the answers here, this is what worked for me and is showing on the first click/focus
function vincularDatePickers() {
$('.mostrar_calendario').live('click', function () {
$(this).datepicker({ showButtonPanel: true, changeMonth: true, changeYear: true, showOn: 'focus' }).focus();
});
}
this needs that your input have the class 'mostrar_calendario'
live is for JQuery 1.3+ for newer versions you need to adapt this to "on"
See more about the difference here http://api.jquery.com/live/
If it still doesn't work, it is because of the cloned id. You can completely remove datepicker like this:
$(selector).removeClass('hasDatepicker').removeAttr('id').datepicker();

Resources