How to find the text in label-for of jQuery mobile Radio and Checkbox with knockout? - jquery-mobile

I'm using jQuery 1.9.1, jQM 1.3 & knockout 2.2.1.
My html is as follows:
<div data-role="page" id="coloursView">
<div data-role="content">
<fieldset data-role="controlgroup">
<legend>Colour:</legend>
<input type="radio" name="colours" data-bind="checked: colour" id="radio-1" value="1" />
<label for="radio-1">Red</label>
<input type="radio" name="colours" data-bind="checked: colour" id="radio-2" value="2" />
<label for="radio-2">Blue</label>
<input type="radio" name="colours" data-bind="checked: colour" id="radio-3" value="3" />
<label for="radio-3">Green</label>
</fieldset>
</div><!--/content -->
</div><!--/page -->
My view model is also very simple:
function ColoursViewModel() {
this.template = "coloursView";
this.colour = ko.observable("1");
this.label = ko.observable(); // custom binding
}
Now, i would like to get the description of the selected colour, not the value.
It seems to me, that i need a custom binding, like this one:
ko.bindingHandlers.label = {
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
$("radio", element).filter(function(el) { return $(el).text() === value; }).prop("checked", "checked");
}
};
But i'm not able to get the text of the related label - the label-for text.
Someone could help?
Thanks in advance

Update
Here is another approach where to find only :checked items and remove white-space in text.
Checkbox
$('input[type=checkbox]').each(function () {
if ($(this).is(':checked')) {
var checkbox = $(this).prev('label').text();
alert('Checkbox: ' + checkbox.replace(/\s+/g, ' '));
}
});
Radio
$('input[type=radio]').each(function () {
if ($(this).is(':checked')) {
var radio = $(this).prev('label').text();
alert('Radio: ' + radio.replace(/\s+/g, ' '));
}
});
Updated Demo
Checkbox
$('div.ui-checkbox').find('span.ui-btn-text').text();
Radio
$('div.ui-radio').find('span.ui-btn-text').text();

Sorry if i answer myself, but i think i got it. At least for radio inputs.
Now, i have a custom binding handler at fieldset level, to keep the markup clean and more readable, as i can:
<fieldset data-role="controlgroup" id="front-colours" data-bind="frontColourLabel: frontColour">
<legend>Front Colour: <span data-bind="text: frontColourDescription"></span> (Value: <span data-bind="text: frontColour"></span>)</legend>
<input type="radio" name="front-colours" data-bind="checked: frontColour" id="fc-radio-1" value="red" />
<label for="fc-radio-1">Red</label>
<input type="radio" name="front-colours" data-bind="checked: frontColour" id="fc-radio-2" value="blue" />
<label for="fc-radio-2">Blue</label>
<input type="radio" name="front-colours" data-bind="checked: frontColour" id="fc-radio-3" value="green" />
<label for="fc-radio-3">Green</label>
</fieldset>
this is the binding handler i come up:
ko.bindingHandlers.frontColourLabel = {
update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
ko.utils.unwrapObservable(valueAccessor());
var id = $('input:radio[name='+element.id+']:checked').prop("id");
var radioText = $('label[for=' + id + ']').text();
viewModel.frontColourDescription(radioText);
}
};
the only tricky part here, is that the id of the fieldset is equal to the name of the radio-group, as it's easy to filter out what radio-group i want to address.
WORKING EXAMPLE: http://jsfiddle.net/h7Bmb/1/
I try now to get the checkbox part to work. Someone can help?

Related

KnockoutJS radio button checked binding that works with JQuery Mobile 1.4?

I've been trying to work out how to get a checked binding to work with Knockout and JQuery Mobile. For some reason the vanilla Knockout JS "checked" binding does not work:
<fieldset data-role="controlgroup">
<legend>Your favorite flavor:legend>
<input type="radio" name="flavor-selection" value="Chocolate" id="flavor-selection-chocolate" data-bind="checked: flavor" />
<label for="flavor-selection-chocolate">Normal</label>
<input type="radio" name="flavor-selection" value="Vanilla" id="flavor-selection-vanilla" data-bind="checked: flavor" />
<label for="flavor-selection-vanilla">Party</label>
</fieldset>
Any ideas why?
It turns out that jQuery Mobile styles the label for the radio button in order to display the radio selection (hiding the actual radio button itself).
I tried the suggestion found here: http://codeclimber.net.nz/archive/2013/08/16/How-to-bind-a-jquery-mobile-radio-button-list-to.aspx but didn't have any success with it - I suspect it might have only worked with a previous version of jQuery Mobile.
Here's my alternative:
Create a custom binding to switch the "ui-radio-on" and "ui-radio-off" classes on the label depending on the checked state of the hidden checkbox:
ko.bindingHandlers.jqMobileRadioChecked = {
init: function (element, valueAccessor, allBindingsAccessor, data, context) {
ko.bindingHandlers.checked.init(element, valueAccessor, allBindingsAccessor, data, context);
},
update: function (element, valueAccessor, allBindingsAccessor, data, context) {
var viewModelValue = valueAccessor();
var viewModelValueUnwrapped = ko.unwrap(viewModelValue);
var $el = $(element);
var $label = $el.siblings("label[for='" + $el.attr("id") + "']");
if (viewModelValueUnwrapped === $el.val()) {
$label.removeClass("ui-radio-off");
$label.addClass("ui-radio-on");
} else {
$label.removeClass("ui-radio-on");
$label.addClass("ui-radio-off");
}
}
};
Then the HTML simply becomes:
<fieldset data-role="controlgroup">
<legend>Your favorite flavor:legend>
<input type="radio" name="flavor-selection" value="Chocolate" id="flavor-selection-chocolate" data-bind="jqMobileRadioChecked: flavor" />
<label for="flavor-selection-chocolate">Normal</label>
<input type="radio" name="flavor-selection" value="Vanilla" id="flavor-selection-vanilla" data-bind="jqMobileRadioChecked: flavor" />
<label for="flavor-selection-vanilla">Party</label>
</fieldset>

how to set radio button checked using knockout.js?

I have two radio buttons.
<td>
<div style="display: inline; margin-right: 10px">
<input type="radio" name="USGlobalUser" data-bind:"checked:IsGlobal/>US
</div>
<div style="display: inline">
<input type="radio" name="USGlobalUser" data-bind:"checked:IsGlobal"/>Global
</div>
</td>
I am populating my model like this
QuestionnaireModel = function (data) {
self.IsGlobal = ko.protectedObservable(data ? data.IsGlobal : false);
}
The value is coming from DB perfectly and its getting populated in self.IsGlobal as true/false. Based upon this true/false, I want to set my radio button checked.
The checked binding works differently for radio buttons:
For radio buttons, KO will set the element to be checked if and only if the parameter value equals the radio button node’s value attribute. So, your parameter value should be a string.
So your IsGlobal should hold a string and you need to have the same string as the value of the radio buttons:
<input type="radio" name="USGlobalUser"
data-bind="checked: IsGlobalCheckbox" value="false" />US
<input type="radio" name="USGlobalUser"
data-bind="checked: IsGlobalCheckbox" value="true" />Global
And in your viewmodel:
self.IsGlobal = ko.observable(data ? data.IsGlobal + "" : "false");
If you want to keep the IsGlobal to store a boolean value you need to create a new computed property for the radio button which does the conversion:
self.IsGlobalCheckbox = ko.computed({
read: function() {
return self.IsGlobal() + "";
},
write: function (v) {
if (v == "true") self.IsGlobal(true)
else self.IsGlobal(false)
}
});
Demo JSFIddle.
And by the way as Tomas noted your binding systax is broken in your sample.
Value from DB is boolean True/False
I changed in viewmodel :
self.IsGlobal = ko.protectedObservable(data ? data.IsGlobal.toString() : "");
and in cshtml :
<td>
<div style="display: inline; margin-right: 10px">
<input type="radio" name="USGlobalUser" value="false" data-bind="checked:IsGlobal()" />US
</div>
<div style="display: inline">
<input type="radio" name="USGlobalUser" value="true" data-bind="checked:IsGlobal()" />Global
</div>
</td>
It`s much more simple. If you want to store something different from string in observable attached to radio buttons just set checkedValue binding for each radio button to same value as html element.
<div style="display: inline; margin-right: 10px">
<input type="radio" name="USGlobalUser" data-bind="checked: IsGlobal, checkedValue: false" value="false" />US</div>
<div style="display: inline">
<input type="radio" name="USGlobalUser" data-bind="checked: IsGlobal, checkedValue: true" value="true" />Global</div>
var QuestionnaireModel = function (data) {
var self = this;
self.IsGlobal = ko.observable(data ? data.IsGlobal : false);
}
ko.applyBindings(new QuestionnaireModel({
IsGlobal: true
}))
After data-bind attribute should be equality sign instead of colon.
<input type="radio" name="USGlobalUser" data-bind="checked:IsGlobal"/>

Jquery-UI radio button

I am using two groups of radio buttons
Group 1:
State
City
Group 2:
A-C
D-H
I-M
N-R
S-Z
When I toggle between state and city, I want A-C from group 2 to be set to checked while the others are set to unchecked.
I have it working in this fiddle here fiddle
HTML:
<div id="sort-radio">
<input type="radio" id="byState" name="sort-radio" checked="checked"/><label for="byState">By State</label>
<input type="radio" id="byCity" name="sort-radio"/><label for="byCity">By City</label>
</div>
<div id="alphabet-radio" style="width:300px;">
<input type="radio" id="A-C" name="alphabet-radio" checked="checked"/>
<label for="A-C">A-C</label>
<input type="radio" id="D-H" name="alphabet-radio"/>
<label for="D-H">D-H</label>
<input type="radio" id="I-M" name="alphabet-radio"/>
<label for="I-M">I-M</label>
<input type="radio" id="N-R" name="alphabet-radio"/>
<label for="N-R">N-R</label>
<input type="radio" id="S-Z" name="alphabet-radio"/>
<label for="S-Z">S-Z</label>
</div>
JavaScript:
$(function () {
$("#sort-radio").buttonset();
});
$(function () {
$("#alphabet-radio").buttonset().find('label').css('width', '19.4%');
});
document.getElementById("byState").addEventListener("click", function () {
document.getElementById("A-C").checked = true;
document.getElementById("D-H").checked = false;
document.getElementById("I-M").checked = false;
document.getElementById("N-R").checked = false;
document.getElementById("S-Z").checked = false;
}, false);
document.getElementById("byCity").addEventListener("click", function () {
document.getElementById("A-C").checked = true;
document.getElementById("D-H").checked = false;
document.getElementById("I-M").checked = false;
document.getElementById("N-R").checked = false;
document.getElementById("S-Z").checked = false;
}, false);
However, when I use this exact code in my website, it does not work (it leaves the previously selected button from group 2 selected). I am using jquery-ui-1.10.1.custom.css which displays the radio buttons nicely, as found here: jquery ui button.
Any clue why this would affect it? When I remove the line <link rel="stylesheet" href="jquery-ui-1.10.1.custom.css" /> from my index.php, it works beautifully.
A few problems:
The button widget works by responding to click events on the radio button's label. This means that the click event you are listening to on the radio buttons themselves won't get fired, since you actually aren't clicking the radio buttons themselves, but their labels. You can work around this by using the change event.
You need to call .buttonset('refresh') after manually updating the checked state of a radio button.
Just setting the checked attribute on one radio button in a group is enough to make the rest become unchecked automatically. You shouldn't need to set the checked property on each one.
You should put your event handlers inside the document.ready handler as well. You can also just use one instead of two.
With all of those things in mind, here are the changes I would make:
$(function () {
$("#sort-radio").buttonset();
$("#alphabet-radio").buttonset().find('label').css('width', '19.4%');
document.getElementById("byState").addEventListener("change", function () {
document.getElementById("A-C").checked = true;
$("#alphabet-radio").buttonset("refresh");
}, false);
document.getElementById("byCity").addEventListener("change", function () {
document.getElementById("A-C").checked = true;
$("#alphabet-radio").buttonset("refresh");
}, false);
});
Example: http://jsfiddle.net/Fzq8L/2/
Since you are using jQuery, you can simplify this a great deal by adding a class to the radio buttons - of which only one can be "set" SO listen to the change event on those. Remove the extra function at the start, pick one of the "array" of buttons to click from the second group. (since only one can be picked)
Simpler version markup :
<div id="sort-radio">
<input type="radio" class="picker" id="byState" name="sort-radio" checked='true'
/>
<label for="byState">By State</label>
<input type="radio" class="picker" id="byCity" name="sort-radio"
/>
<label for="byCity">By City</label>
</div>
<div id="alphabet-radio" style="width:300px;">
<input type="radio" class="secondgroup" id="A-C" name="alphabet-radio"
checked='true' />
<label for="A-C">A-C</label>
<input type="radio" class="secondgroup" id="D-H" name="alphabet-radio"
/>
<label for="D-H">D-H</label>
<input type="radio" class="secondgroup" id="I-M" name="alphabet-radio"
/>
<label for="I-M">I-M</label>
<input type="radio" class="secondgroup" id="N-R" name="alphabet-radio"
/>
<label for="N-R">N-R</label>
<input type="radio" class="secondgroup" id="S-Z" name="alphabet-radio"
/>
<label for="S-Z">S-Z</label>
</div>
Code:
$(document).ready(function () {
$("#sort-radio").buttonset();
$("#alphabet-radio").buttonset().find('label').css('width', '19.4%');
});
$(".picker").change(function () {
$('.secondgroup').eq($('.picker').index(this)).prop("checked", true);
$('#alphabet-radio').buttonset('refresh');
});
Working example:http://jsfiddle.net/MarkSchultheiss/8x28x/2/
Set back second group, first to item when either of first group is changed:
$(document).ready(function () {
$("#sort-radio").buttonset();
$("#alphabet-radio").buttonset().find('label').css('width', '19.4%');
});
$(".picker").change(function () {
$('.secondgroup').eq(0).prop("checked", true);
$("#alphabet-radio").buttonset("refresh");
});
Fiddle for that: http://jsfiddle.net/MarkSchultheiss/8x28x/3/

jQuery Mobile and Knockout.js templating, styling isnt applied

Ok so this is beginning to drive me insane. I have for several hours now searched and searched, and every single solution doesnt work for me. So yes, this question might be redundant, but i cant for the life of me get solutions to work.
I have a bunch of checkboxes being generated by a jquery template that is databound via knockout.js. However, it turns up unstyled. Afaik, it is something about jquery mobile does the styling before knockout renderes the template, so it ends up unstyled.
I have tried numerous methods to no avail, so i hope someone here can see what i am doing wrong.
(i am using jquery mobile 1.2.0 , jquery 1.8.2 and knockout 2.2.1)
This is the scripts:
<script type="text/javascript">
jQuery.support.cors = true;
var dataFromServer = "";
// create ViewModel with Geography, name, email, frequency and jobtype
var ViewModel = {
email: ko.observable(""),
geographyList: ["Hovedstaden","Sjælland","Fyn + øer","Nordjylland","Midtjylland","Sønderjylland" ],
selectedGeographies: ko.observableArray(dataFromServer.split(",")),
frequencySelection: ko.observable("frequency"),
jobTypes: ["Kontor (administration, sekretær og reception)","Jura","HR, Ledelse, strategi og udvikling","Marketing, kommunikation og PR","Handel og service (butik, service, værtinde og piccoline)","IT","Grafik og design","Lager, chauffør, bud mv.","Økonomi, regnskab og finans","Kundeservice, telefoninterview, salg og telemarketing","Sprog","Øvrige jobtyper"],
selectedJobTypes: ko.observableArray(dataFromServer.split(",")),
workTimes: ["Fulltid","Deltid"],
selectedWorkTimes: ko.observableArray(dataFromServer.split(","))
};
// function for returning checkbox selection as comma separated list
ViewModel.selectedJobTypesDelimited = ko.dependentObservable(function () {
return this.selectedJobTypes().join(",");
}, ViewModel);
var API_URL = "/webapi/api/Subscriptions/";
// function used for parsing json message before sent
function omitKeys(obj, keys) {
var dup = {};
var key;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
if (keys.indexOf(key) === -1) {
dup[key] = obj[key];
}
}
}
return dup;
}
//Function called for inserting new subscription record
function subscribe() {
if($("#jobmailForm").valid()=== true){
//window.alert("add subscriptiooncalled");
var mySubscription = ko.toJS(ViewModel);
//var json = JSON.stringify(mySubscription);
var jsonSmall = JSON.stringify(omitKeys(mySubscription, ['geographyList','jobTypes','selectedJobTypesDelimited','workTimes']));
//window.alert(jsonSmall);
$.ajax({
url: API_URL,
cache: false,
type: 'POST',
contentType: 'application/json',
data: jsonSmall,
success: function (data) {
window.alert("success");
},
error: function (error) {
window.alert("ERROR STATUS: " + error.status + " STATUS TEXT: " + error.statusText);
}
});
}
}
function initializeViewModel() {
// Get the post from the API
var self = this; //Declare observable which will be bind with UI
// Activates knockout.js
ko.applyBindings(ViewModel);
}
// Handle the DOM Ready (Finished Rendering the DOM)
$("#jobmail").live("pageinit", function() {
initializeViewModel();
$('#jobmailDiv').trigger('updatelayout');
});
</script>
<script id="geographyTmpl" type="text/html">
<input type="checkbox" data-role="none" data-bind="attr: { value: $data }, attr: { id: $data }, checked: $root.selectedGeographies" />
<label data-bind="attr: { for: $data }"><span data-bind="text: $data"></span></label>
</script>
<script id="jobTypeTmpl" type="text/html">
<label><input type="checkbox" data-role="none" data-bind="attr: { value: $data }, checked: $root.selectedJobTypes" /><span data-bind="text: $data"></span></label>
</script>
Note, "jobmail" is the surrounding "page" div element, not shown here. And this is the markup:
<div data-role="content">
<umbraco:Item field="bodyText" runat="server"></umbraco:Item>
<form id="jobmailForm" runat="server" data-ajax="false">
<div id="jobmailDiv">
<p>
<label for="email">Email</label>
<input type="text" name="email" id="email" class="required email" data-bind="'value': email" />
</p>
<fieldset data-role="controlgroup" data-mini="true" data-bind="template: { name: 'geographyTmpl', foreach: geographyList, templateOptions: { selections: selectedGeographies } }">
<input type="checkbox" id="lol" />
<label for="lol">fkfkufk</label>
</fieldset>
<fieldset data-role="controlgroup" data-mini="true">
<p data-bind="template: { name: 'jobTypeTmpl', foreach: jobTypes, templateOptions: { selections: selectedJobTypes } }"></p>
</fieldset>
<fieldset data-role="controlgroup" data-mini="true">
<input type="radio" id="frequency5" name="frequency" value="5" data-bind="checked: frequencySelection" /><label for="frequency5">Højst 5 gange om ugen</label>
<input type="radio" id="frequency3" name="frequency" value="3" data-bind="checked: frequencySelection" /><label for="frequency3">Højst 3 gange om ugen</label>
<input type="radio" id="frequency1" name="frequency" value="1" data-bind="checked: frequencySelection" /><label for="frequency1">Højst 1 gang om ugen</label>
</fieldset>
<p>
<input type="button" value="Tilmeld" class="nice small radius action button" onClick="subscribe();">
</p>
Tilbage
</div>
</form>
Alternate method of invoking the restyling (doesnt work either):
$(document).on('pagebeforeshow', '#jobmail', function(){
// Get the post from the API
var self = this; //Declare observable which will be bind with UI
// Activates knockout.js
ko.applyBindings(ViewModel);
});
// Handle the DOM Ready (Finished Rendering the DOM)
$("#jobmail").live("pageinit", function() {
$('#jobmail').trigger('pagecreate');
});
Use a custom binding (Knockout) to trigger jQuery Mobile to enhance the dynamically created content produced by Knockout.
Here is a simple custom binding:
ko.bindingHandlers.jqmEnhance = {
update: function (element, valueAccessor) {
// Get jQuery Mobile to enhance elements within this element
$(element).trigger("create");
}
};
Use the custom binding in your HTML like this, where myValue is the part of your view model that changes, triggering the dynamic content to be inserted into the DOM:
<div data-bind="jqmEnhance: myValue">
<span data-bind="text: someProperty"></span>
My Button
<input type="radio" id="my-id" name="my-name" value="1" data-bind="checked: someOtherProperty" /><label for="my-id">My Label</label>
</div>
In my own case, myValue was part of an expression in an if binding, which would trigger content to be added to the DOM.
<!-- ko if: myValue -->
<span data-bind="jqmEnhance: myValue">
<!-- My content with data-bind attributes -->
</span>
<!-- /ko -->
Every dynamically generated jQuery Mobile content must be manually enhanced.
It can be done in few ways, but most common one can be done through the jQuery Mobile function .trigger( .
Example:
Enhance only page content
$('#page-id').trigger('create');
Enhance full page (header + content + footer):
$('#page-id').trigger('pagecreate');
If you want to find more about this topic take a look my other ARTICLE, to be more transparent it is my personal blog. Or find it HERE.

CheckBOX ASP MVC

Hi i am new to ASP.NET MVC. I am not sure how to deal with Check box or Radio Button to get values when they are clicked. Can any one help me? I am providing a simple code that might help you understand what i meant to be. Please share examples.
<script type="text/javascript" >
function check(browser)
{
document.getElementById("answer").value=browser;
} </script>
<form action="">
<input type="radio" name="browser"
onclick="check(this.value)"
value="Internet Explorer"/>Internet
Explorer<br />
<input type="radio" name="browser"
onclick="check(this.value)"
value="Firefox"/>Firefox<br />
<input type="radio" name="browser"
onclick="check(this.value)"
value="Netscape"/>Netscape<br />
<input type="radio" name="browser"
onclick="check(this.value)"
value="Opera"/>Opera<br />
<br />
Your favorite browser is: <input type="text" id="answer"
size="20"/> </form>
controller code
public ActionResult Index()
{
ViewData["list"] = new[]
{
new SelectListItem {Text = "InternetExplorer", Value = "InternetExplorer"},
new SelectListItem {Text = "Firefox", Value = "Firefox"},
new SelectListItem {Text = "Safari", Value = "Safari"},
new SelectListItem {Text = "Opera", Value = "Opera"}
};
return View();
}
[AcceptVerbs(HttpVerbs.Post),ActionName("Index")]
public ActionResult IndexPost(string browser)
{
// ...
}
view code
<% using (Html.BeginForm()) { %>
<% foreach(var item in (IEnumerable<SelectListItem>)ViewData["list"]) { %>
<label>
<% = Html.RadioButton("browser", item.Value) %>
<% = item.Text %></label>
<% } %>
<input type="submit" value="Select" />
<% } %>
<script type="text/javascript" src="<% = Url.Content("~/Scripts/jquery-1.3.2.js") %>" ></script>
<script type="text/javascript">
$(function() {
$("form:first").submit(function(e) {
e.preventDefault();
alert($(this).find(":radio:checked").val());
});
});
</script>
If you want browser value in action, you coding in IndexPost method.
or you want in javascript, onsubmit or onclick(and other) event handling, get checked radiobutton value at jQuery.
This was logic taken from: http://byatool.com/mvc/asp-net-mvc-how-to-handle-multiple-checkboxes-with-viewsactions-jquery-too/. I simply modified it very minimally.
----------
HTML Part|
----------
{form action="/Test/CheckForIds/" method="post"}
{div}
{input type="checkbox" name="IdList" value="1" /}
{input type="checkbox" name="IdList" value="2" /}
{input type="checkbox" name="IdList" value="3" /}
{input type="checkbox" name="IdList" value="4" /}
{/div}
{div}
{input type="submit" value="go" /}
{/div}
{/form}
----------------
Controller Part|
----------------
{AcceptVerbs(HttpVerbs.Post)} _
Function GroupPageSend(ByVal selectedObjects() As String) As ActionResult
{!--- YOUR CODE GOES HERE ---}
EX//
For Each item In selectedObjects
If i = 0 Then
string = Trim(item)
i = i + 1
Else
string = string & "," & Trim(item)
End If
Next
End Function
The above will gather values from selected checkboxes and will allow you to manage results.
Keep in mind all { = < and all } = >
I am probably not getting your question, but your sample will work well.
When you submit the form and the controller's method is called asp.net mvc will set the "browser" parameter to the value of the selected radio button's value.
hai friend try this,
<asp:RadioButton ID="RadioButton1" runat="server" onmousedown="yourjsfunc();" />

Resources