Binding boolean values to radio buttons - ractivejs

When I bind a boolean variable to radio buttons with true/false values, the radio buttons' checked status does not get set when the template first loads -- both remain unchecked.
new Ractive({
template: "#template",
el: "#output",
data: {
accept: true
}
});
<script src="//cdn.ractivejs.org/latest/ractive.js"></script>
<div id="output"></div>
<script id="template" type="text/html">
<input type="radio" name="{{ accept }}" value="true" /> Yes
<input type="radio" name="{{ accept }}" value="false" /> No
<br/>
accept = {{ accept }}
</script>
But once I click the radio buttons, their checked statuses do become in sync with the boolean variable.
How can I get this binding to work? Is it a bug with Ractive or am I doing something wrong?
I can work around the problem by changing my boolean variable to a string (accept: "true") but that really wouldn't be ideal.

Computed property will be an overkill for this case. Actually, you were close enough on your original example. Just try the following (only change is at value="{{true}}" instead of value="true"):
new Ractive({
template: "#template",
el: "#output",
data: {
accept: false
},
});
<script src="//cdn.ractivejs.org/latest/ractive.js"></script>
<div id="output"></div>
<script id="template" type="text/html">
<input type="radio" name="{{ accept }}" value="{{true}}"/> Yes
<input type="radio" name="{{ accept }}" value="{{false}}"/> No
<br/>
accept = {{ accept }}
<button on-click="toggle('accept')">toggle</button>
</script>

To my knowledge, ractive types everything hard coded in the template value props of inputs to strings. Illustrated here.
However properties in your data-object does obviously retain their types. Usually multiple different values is what you use radio buttons for anyways. A simple "true/false" bool doesn't need more than a checkbox. Ugly example of binding your radio buttons to bool objects here. (PS: Obviously not recommended).

Related

How do I handle a boolean HTML attribute in a Handlebars partial?

I'm writing a fun little project to build up my HTML/JS skills. I'm using Handlebars to render some forms, and I hit something I can't seem to get around.
I've registered this as a partial template named 'checkbox':
<label>
<input
type="checkbox"
id="{{id}}"
name="{{id}}"
value="true">
{{labelText}}
</label>
That did me well when I was making forms to add data, but now I'm making forms to edit data, so I want to make the checkbox checked if the current item already is checked. I can't figure out how to make this work.
The first thing I tried was something like this:
<label>
<input
type="checkbox"
id="{{id}}"
name="{{id}}"
value="true"
checked="{{isChecked}}">
{{labelText}}
</label>
But if I pass that values like isChecked=true I get a checked box every time, because I guess for that kind of attribute in HTML being present at all means 'true'. OK.
So I tried using the if helper:
<input
type="checkbox"
id="{{id}}"
name="{{id}}"
value="true"
{{#if isChecked}}checked{{/if}}>
{{labelText}}
This sort of works. If I omit the isChecked property entirely, the box is unchecked. If I hard-code a true or false value like this, it works:
{{> checkbox id="test" labelText="test" isChecked=true }}
But I can't seem to get what I want with a value there. For example, if I try:
{{> checkbox id="test" labelText="test" isChecked="{{someCondition}}" }}
It seems like the condition isn't properly being resolved because I always get the attribute in that case.
What am I missing? I feel like there should be a way to do this, but I'm running out of tricks.
You cannot put an expression inside of another expression:
{{> checkbox id="test" labelText="test" isChecked="{{someCondition}}" }}
From examples you wrote I assume the problem you are having is related to how you pass the context - id and labelText are hardcoded while isChecked is expected to be a variable of some sort. In reality all those should be variables. Consider the following example - HTML:
<div id="content"></div>
<script id="parent-template" type="text/x-handlebars-template">
{{#each checkboxes}}
{{> checkbox this }}<br>
{{/each}}
</script>
<script id="partial-template" type="text/x-handlebars-template">
<input
type="checkbox"
id="{{id}}"
name="{{id}}"
value="true"
{{#if isChecked}}checked{{/if}}>
{{labelText}}
</script>
JS:
var parentTemplate = Handlebars.compile($("#parent-template").html());
Handlebars.registerPartial({
checkbox: Handlebars.compile($("#partial-template").html())
});
$('#content').html(parentTemplate(
{checkboxes: [
{id: 1, labelText: "test 1", isChecked: true},
{id: 2, labelText: "test 2", isChecked: false},
]}
));

RactiveJS dynamic variable name

I'm curious if I can somehow use dynamic variable names in templates. For example, I'm having a loop, though a type of units in my game:
{{# config.units:unit }}
<input type="text" id="unit_{{unit}}" class="toTrain selectable" value="" placeholder="0" />
{{/ config }}
Where the value of the input should return the value of {{units_1}} for example, which represents the amount of units (type 1).
I could easily do some external object and store the amount of units for each of them but, I was wondering if I can keep the data binded because somewhere in the template there will be a total needed resources which is calculated whith these values.
The only "solution" which came into my head was to get rid of the loop and manually write the units in the template. But, when units change, I also need to change the template, and.. the real template structure for one unit is a bit bigger than this snippet.
Example:
<input value="{{units_1}}" />
<input value="{{units_2}}" />
And I was looking for something like:
<input value="{{'units_'+unit}}" />
Which is obviously not working and not even supposed to work this way. But, thats why I'm here right ? To raise questions.
Regards !
Try to use write getUnit function:
{{# config.units:unit }}
<input type="text" id="{{ getUnit(unit) }}" class="toTrain selectable" value="" placeholder="0" />
{{/ config }}
Component:
Ractive.extend({
init:function(){
self.set("getUnit", function (id) {
return self.get("config.units.unit_"+id);
});
}
})

knockout.js boolean data-binding issues with radio buttons

I'm currently doing the following to compensate for boolean's not mapping well to radio buttons. I am stuck binding 1 and 0 to the value (instead of true and false) because of how the fields are read out of the observables. The value of Pref1/Pref2 come as true/false boolean values from the server. The key here is I want to not only data-bind the checked value of the radio button to match the true/false in the object, but I also want the boolean value of true/false to be written back into the GraduationClass object. My compensation code is not only ugly, but not scalable.
<input type="radio" value="1" name="radioGroup" data-bind="checked: Pref1" />Yes
<input type="radio" value="0" name="radioGroup" data-bind="checked: Pref2" />No
Save
function SiteSettingsViewModel() {
var self = this;
this.saveGraduationClass = function(graduationClass) {
// hack until i get a custom radio button binding
if (graduationClass.Pref1() == 1) {
graduationClass.Pref1(true);
} else {
graduationClass.Pref1(false);
}
if (graduationClass.Pref2() == 1) {
graduationClass.Pref2(true);
} else {
graduationClass.Pref2(false);
}
// ...ajax call to save graduationClass to the server
}
function GraduationClass(data) {
var self = this;
ko.mapping.fromJS(data, {}, this);
}
Here is example from knockoutJs website, that demonstrate how to use radio buttons with
"checked" attribute:
<p>Send me spam: <input type="checkbox" data-bind="checked: wantsSpam" /></p>
<div data-bind="visible: wantsSpam">
Preferred flavor of spam:
<div><input type="radio" name="flavorGroup" value="cherry" data-bind="checked: spamFlavor" /> Cherry</div>
<div><input type="radio" name="flavorGroup" value="almond" data-bind="checked: spamFlavor" /> Almond</div>
<div><input type="radio" name="flavorGroup" value="msg" data-bind="checked: spamFlavor" /> Monosodium Glutamate</div>
</div>
<script type="text/javascript">
var viewModel = {
wantsSpam: ko.observable(true),
spamFlavor: ko.observable("almond") // Initially selects only the Almond radio button
};
// ... then later ...
viewModel.spamFlavor("msg"); // Now only Monosodium Glutamate is checked
</script>
But I dont understand why you use two objects - "Pref1" and "Pref2" fro one radiobutton group "radioGroup"? In this case you just could use one object as in an example used "spamFlavor".
So, please, describe more ditaily what you want to bind: one radiobuttons group by one selected value, or something else.
Also you could use computed observables to calculate different values, please see example.

using handlebars bindAttr for checkbox

I'm using handlebars in a backbone.js rails app, and I have a Boolean field I'm populating with a checkbox.
When I load the edit page, the form is populated with the contents from the server JSON something like
{id:3,user:'test',checkbox:1}
now in my handlebar form, I want to show that the checkbox is 1.
< input type="checkbox" name="checkbox" value="1" {{#if checkbox}} {{bindAttr checkbox checked="isSelected"}}{{/if}} >
but this isn't returning the checked checkbox. I'd really like to just be able to say if checkbox==1, but I don't see how I can do that with handlebars.
Anysuggestions??
What you would usually do, is using a Boolean in the 'model'.
{
isChecked: true
}
and then
<input type="checkbox" {{bindAttr checked="isChecked"}}>
If the Boolean is true, it will render the checked property, and if the Boolean is false, it would omit the property. So if isChecked is true, then Handlebars would output
<input type="checkbox" checked>
and if isChecked were false, we would get
<input type="checkbox">
Which is what we want!
I also wrote a helper to do this. It doesn't use backbone.js, so may be an alternative for some:
Handlebars.registerHelper('checked', function(currentValue) {
return currentValue == '1' ? ' checked="checked"' : '';
});
Usage example:
<input type="checkbox" name="cbxExample" id="cbxExample" {{checked cbxExample}}/>
Would tick a checkbox if the supplied JSON was:
{"cbxExample" : "1"}
Resulting in:
<input type="checkbox" name="cbxExample" id="cbxExample" checked="checked" />
[my first post - hope that's helpful!]

jQuery with ASP.NET WebForms - disabling textboxes

Another jQuery noob question - what am I doing wrong??
I have some HTML markup rendered by ASP.NET 3.5 webforms which looks like this:
<input id="ctl01_cphContent_pnlBasicInfo_chkRC"
type="checkbox" name="ctl01$cphContent$pnlBasicInfo$chkRC" />
<label for="ctl01_cphContent_cntPromos_pnlBasicInfo_chkRC">Recurrent Charges</label>
<span id="ctl01_cphContent_cntPromos_pnlBasicInfo_lblPromoValidFor"
class="rcPromo">Validity:</span>
<span class="rcPromo">
<input id="ctl01_cphContent_pnlBasicInfo_rbnDiscountValidFor"
type="radio" name="ctl01$cphContent$pnlBasicInfo$discountValidFor"
value="rbnDiscountValidFor" checked="checked" />
<label for="ctl01_cphContent_cntPromos_pnlBasicInfo_rbnDiscountValidFor">valid for</label>
</span>
<span class="rcPromo">
<input id="ctl01_cphContent_pnlBasicInfo_rbnDiscountValidUntil"
type="radio" name="ctl01$cphContent$pnlBasicInfo$discountValidFor"
value="rbnDiscountValidUntil" />
<label for="ctl01_cphContent_cntPromos_pnlBasicInfo_rbnDiscountValidUntil">valid until</label>
</span>
<input name="ctl01$cphContent$pnlBasicInfo$txtDiscountMonths" type="text"
id="ctl01_cphContent_pnlBasicInfo_txtDiscountMonths"
class="textbox" class="rcPromo" originalValue="" style="width:30px;" />
<span id="ctl01_cphContent_cntPromos_pnlBasicInfo_lblMonths" class="rcPromo"></span>
<input name="ctl01$cphContent$pnlBasicInfo$txtDiscountUntil" type="text"
id="ctl01_cphContent_pnlBasicInfo_txtDiscountUntil"
class="textbox" class="rcPromo" originalValue="" style="width:150px;" />
I have a checked "chkRC" which I want to trap and use to enable/disable other UI controls
I have a number of labels, input (type=radio) and input (type=text) UI controls. These are all marked with the "rcPromo" dummy CSS class
I have a CSS class called "textbox" for the normal textbox and "textboxDisabled" for the disabled state of the textbox, in an externally referenced CSS file, that work OK (when used in server-side code, that is)
What I'm trying to accomplish in jQuery is this: when the "chkRC" checkbox is disabled, I want to disable all relevant UI controls.
My jQuery looks like this:
$(document).ready(function() {
$("#<%= chkRC.ClientID %>").click(function() {
$('.rcPromo > :label').toggleClass('dimmed');
if (this.checked) {
$('.rcPromo').removeAttr('disabled');
$('.rcPromo .textboxDisabled').addClass('textbox').removeClass('textboxDisabled');
}
else {
$('.rcPromo > :input').removeAttr('checked');
$('.rcPromo .textbox').addClass('textboxDisabled').removeClass('textbox');
$('.rcPromo').attr('disabled', true);
}
});
});
It works fine for the labels and the radiobuttons - but I just can't get it to work with the textboxes - they just stay the same all around, nothing changes (they don't get disabled and they don't change their appearance to indicate that they're disabled, either).
I don't understand this - I do see several (a few more than in the sample) textboxes, which are <input type="text"> in HTML, and they do have the class="rcPromo" and class="textbox" on them - so why doesn't jQuery find and update those?
Any ideas?
Marc
I can't think of a way to augment the css class names that are assigned to controls from the skin file (phoenix is correct, the class names need to be added in the same attribute).
I can think of a few workarounds though:
--> You can wrap all the textboxes you want disabled in a div with a given class:
<div class="disable_textbox"><asp:textbox id="".../></div>
and then disable them by selecting:
$('.disable_textbox input').attr('disabled', true);
--> You can include character strings in the ID of the textboxes you want disabled:
<asp:textbox id="txtDiscountUntil_DisableMe" ... />
and then disable them like so:
$("input[id*='DisableMe']").attr('disabled', true);
--> You can add a custom attribute to your textbox:
txtDiscountUntil.Attributes.Add("disableme", "true");
and then disable them like so:
$("input[disableme='true']").attr('disabled', true);
Your HTML markup is not the correct one.
You can't add two classes like the one in your code.
Two classes can be added like this
<input type="text" class="Class1 Class2" />
and not like
<input type="text" class="Class1" class="Class2" />
Why don't you use hasClass to check whether the element has this class set or not?
I think you have to give this in an OR condition for the two classes.

Resources