I am knew to knockout and have a question about how to do some conditional binding. I have a dropdown input that shows and hides other inputs depending upon the option that is selected. I have that working but I am having a problem when I load the page after the page has already been posted previously. I am able to GET the dropdown inputs that was previously selected and posted but the binding that takes place (showing and hiding) of the other inputs is not triggered. Please see below:
<script>
function ViewModel() {
this.selectedPet = ko.observable();
var petArray = ["Dog", "Cat", "Fish"];
this.petOptions = ko.observableArray(petArray);
};
ko.applyBindings(new ViewModel);
</script>
<form>
<select data-bind="options: petOptions, value: selectedPet" asp-for="Pets">
</select>
<input data-bind="visible: petOptions() === "Dog" asp-for="DogFood" />
<input data-bind="visible: petOptions() === "Cat" asp-for="CatFood" />
<input data-bind="visible: petOptions() === "Fish" asp-for="FishFood" />
</form>
I figured out what I needed to do. I need to set the initial observable value to the value that was posted.
var onLoadPet = "#Model.Pet.Value";
function ViewModel() {
this.selectedPet = ko.observable(onLoadPet);
}
Related
I'm trying to get the value of each checked box that has been selected as true. Each time I select a checkbox it grabs the value of that checkbox instead of all the selected checkboxes.
Path: talentList.html
<fieldset>
<div class="checkbox">
<label>
<input name="specialisation" type="checkbox" value="Accounting Firm"> Accounting Firm
</label>
</div>
<div class="checkbox">
<label>
<input name="specialisation" type="checkbox" value="Accounting in Industry"> Accounting in Industry
</label>
</div>
</fieldset>
Path: talentList.js
Template.talentList.events({
'change [name="specialisation"]': function ( event, template ) {
let specialisation = event.target.value;
template.candidateListFilter.set( specialisation );
}
});
There is only one target set in the event handler so event.target.value will be a scalar instead of an array. You need to iterate over the array of checkboxes.
Template.talentList.events({
'change [name="specialisation"]': function ( event, template ) {
$.each($('[name="specialisation"]'),function(i,cb){
let specialisation = cb.value;
template.candidateListFilter.set( specialisation );
});
}
});
To be honest this seems like an odd pattern. If you want to update a document whenever a checkbox is checked/unchecked you shouldn't have to set the state of all the other checkboxes at the same time, you should be able to just poke the one you want.
Not sure if this is correct. It creates an object of all selected options.
'change [name="specialisation"]': function ( event, template ) {
$(document).ready(function(){
var specialisation = $('input[name="specialisation"]:checked').map(function(){
return $(this).val();
});
var specialisationListArray = specialisation.get();
template.candidateListFilter.set( specialisationListArray );
});
},
I am new to Meteor :)
I have a template helper:
userRoleMap: function() {
var u = getUser();
if (u) {
var lstRoles = Meteor.roles.find({}).fetch();
var userRoles = u.roles ? u.roles : [];
_.map(lstRoles, function(r) {
_.extend(r, {
userMapped: _.contains(userRoles, r.name)
});
return r;
});
return lstRoles;
}
return [];
}
I am using this helper in my template as:
{{#each userRoleMap}}
<div class="checkbox">
<label>
<input type="checkbox" class="chkUserRole" value="{{name}}" checked="{{userMapped}}"> {{name}}
</label>
</div>
{{/each}}
I am showing the above html/template in a bootstrap-modal. I am showing this modal on click of a button (and setting user-id in a Session which I am using when calling getUser() function).
The issue is the checkbox check state is not changing based on value of "userMapped". It is getting set correctly first time, but not afterwards. The helper userRoleMap is getting called every-time I open modal, but the checkboxes are having same checked state which they had when it was opened previously (manual checks/unchecks are getting maintained).
The return value of helper method is working as expected (verified by logging it on console).
Anything I am missing here ? Something to do with _.extend() ?
The Meteor way to do this is to either return checked as an element attribute or not:
Template.registerHelper( 'checked', ( a, b ) => {
return a === b ? 'checked' : '';
});
{{#each userRoleMap}}
<div class="checkbox">
<label>
<input type="checkbox" class="chkUserRole" value="{{name}}" {{checked userMapped true}}> {{name}}
</label>
</div>
{{/each}}
I have a list of forms in a page of my meteor app, the list is generated dynamically and all the forms have the same class.
So i made the event submit on the events area of my template, but when i submit the form, only the first form works, if i submit the second form for example, meteor event understand that the event came from the first, and i don'k know how to pass the form id to meteor events, so i can't get the data from the right form. Someone can help me?
This is my event:
'submit .form-equation': function (e, t) {
e.preventDefault();
var name = t.find('#name').value,
equation = t.find('#equation').value,
order = Number(t.find('#order').value),
isChart = t.find('#isChart').checked;
var equationData = {
name: name,
equation: equation,
order: order,
isChart: isChart
};
var station = Stations.findOne(Session.get('stationNewID'));
var sensorId = t.find('#sensorId').value;
Meteor.call('insertEquation', station, sensorId, equationData, function (error, result) {
if (error)
console.log(error);
});
}
I think there is something else wrong with your application. The behavior you described (having multiple forms of the same class with different IDs) works correctly on a clean example.
Check out the demo I made that demonstrates this: http://meteorpad.com/pad/8CPL2xvS7taeL6jZS/MultipleFormSubmitExample
Basically, the forms look like this:
<template name="example">
<form id="1" class="yolo">
<input type="submit" value="Submit">
</form>
<form id="2" class="yolo">
<input type="submit" value="Submit">
</form>
<form id="3" class="yolo">
<input type="submit" value="Submit">
</form>
</template>
And there is only one event listener:
Template.leaderboard.events({
'submit .yolo': function (e, t) {
e.preventDefault();
alert($(e.target).attr('id'));
}
});
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.
I'm having a dropdown list in my web page. And it contains two lists. 1. Yes 2.No. If we select yes then the desired text box and label will visible, else it won't be visible. So how to do this?
You can use javascript to do this. Something like
<script type="text/javascript">
function ChangeSel(val)
{
var tYes = document.getElementById("txtYes");
if ( val === "1" )
{
tYes.style.display = "inline";
}
else
{
tYes.style.display = "none";
}
}
</script>
<select id="sel1" onchange="ChangeSel(this.value);">
<option value="1">Yes</option>
<option value="2">No</option>
</select>
<input type="text" id="txtYes" value="" />
See a working demo.
You can do this using a post to the server side. Note that they use a button to hide the dropdown instead of the other way around, but the concept is the same.
Or you can do this using javascript. Basically you add a javascript function the the ASP:DropDownList's OnChange event.
Also see the tutorials at The official ASP.Net Tutorial Site.