knockout radio button checked status not updated in UI - javascript

In my knockout application, I'm trying to handle a few radio inputs in a forEach loop.
The click event updated the checked properties, but the same is not reflected in the UI of the radio button.
Below ID is the entire Dropdown html :
<ul class="dropdown-menu padding-left padding-right customscroll" data-bind="stoppropgattion:'ss'">
<!--ko foreach:MyPlans-->
<li>
<div class="radio radio-adv">
<label data-bind="attr:{for:$data.Id_$index}" for="cs_plan">
<input class="access-hide" id="cs_plan" data-bind="value:$data.Selected,checked:$data.Selected,attr:{id:$data.Id_$index,name:true},click:UpdatedSelectedPlan" name="Plan" type="radio" />
<span> <!--ko text:$data.Name--><!--/ko--><!--ko if:$data.IsDefault--><span> (Default)</span><!--/ko--></span><span class="circle"></span><span class="circle-check"></span>
</label>
</div>
</li>
<!--/ko-->
</ul>
And on clicking I'm updating the selected response also:
UpdatedSelectedPlan = function (data, event) {
selF.MyPlans.filter(function (elem) {
elem.Selected(false);
});
data.Selected(true);
}
Selected value is updated properly, but the same is not reflected in the UI.
When the Dropdown loads the correct radio is shown as selected, but on click the clicked radio is not getting changed UI wise even though selected value is updated .
Please guide
Thanks
Shruti Nair

use "change" event instead of "click". Radio and checkbox have change trigger.
function vm(){
var self = this;
self.MyPlans = ko.observableArray([
{Id:1, Name:'A', Selected:ko.observable(false), IsDefault:true},
{Id:2, Name:'B', Selected:ko.observable(false), IsDefault:false},
{Id:3, Name:'C', Selected:ko.observable(false), IsDefault:false},
{Id:4, Name:'D', Selected:ko.observable(false), IsDefault:false},
{Id:5, Name:'E', Selected:ko.observable(true), IsDefault:false},
]);
self.UpdatedSelectedPlan = function (data, event) {
self.MyPlans().filter(function (elem) {
elem.Selected(false);
});
data.Selected(true);
}
}
ko.applyBindings(new vm())
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<!--ko foreach:MyPlans-->
<li>
<div class="radio radio-adv">
<label data-bind="attr:{for:$data.Id_$index}" for="cs_plan">
<input class="access-hide" id="cs_plan" data-bind="checked:$data.Selected,value:$data.Selected, attr:{id:$data.Id_$index,name:true},event:{change:$parent.UpdatedSelectedPlan}" name="Plan" type="radio" />
<span> <!--ko text:$data.Name--><!--/ko--><!--ko if:$data.IsDefault--><span> (Default)</span><!--/ko--></span><span class="circle"></span><span class="circle-check"></span>
selected ? <span data-bind="text:Selected"></span>
</label>
</div>
</li>
<!--/ko-->
</ul>

Added return true to the method and it worked.
UpdatedSelectedPlan = function (data, event) {
selF.MyPlans.filter(function (elem) {
elem.Selected(false);
});
data.Selected(true);
return true;
}

Related

How can we achieve product filter page using angularjs with multi selection of checkboxes?

I have created a tabular page in which i need to filter the table with filters using a left side facets boxes of different category but with multi-selection options and i need to use Angularjs for this requirement.
I need to check/uncheck using the clear filter selection .
Any helping library can help to achieve the same or we need to do some logic around the checkboxes to achieve this.
My checkbox code looks like this:
<div class="col-sm-2" style="padding-top: 10px; padding-bottom: 20px;">
<div class="facetBx sltBx" ng-show="tabFilters.length > 0">
<p class="facetBxTitle"><i class="fa fa-filter"></i> Filter Selection
<a class="clrSlt" ng-click="clearAllFilters();">Clear</a>
</p>
<div class="facetBxChld" id="uRslctn">
<ul>
<li ng-repeat="item in tabFilters">
<div class="crop">
<strong title="{{item}}">{{item}}</strong>
</div>
<i class="fa fa-remove rmvThs" style="font-size: 14px;color:#000;float: right;" ng-click="checkItem(item, item,false);"></i>
</li>
</ul>
</div>
</div>
<div class="facetBx" ng-repeat="item in filters">
<p class="facetBxTitle bomtype">{{item.label}}</p>
<div class="facetBxChld" id="bomFacet">
<ul class="multiselect" style="max-height: 140px;overflow-y: auto;">
<li ng-repeat="(k,v) in item.values">
<input type="checkbox" ng-model='isSelected' ng-click='checkItem(item.name, k, isSelected)'>
<span> {{k}} ({{v}})</span>
</li>
<li ng-show="value.length == 0">
No Data Available.
</li>
</ul>
</div>
</div>
</div>
Below website are the reference of the code which i am trying to build:
www.jabong.com
The UI(HTML) is done but i am facing the trouble in the maintaining the checking and un-checking of the checkboxes which are not clearing off.
I believe i need to code something in the ng-model of checkbox to achieve it but i am not able to be successfull so need help on the same.
Sample Plunkur for the same:
enter link description here
Thanks in advance.
Basically you need to keep track of ng-model of checkboxes with some property in your $scope. I did this by modifying your $scope.filters and adding selected property inside it, like below.
var filters = [{
label: 'Brand',
name: 'brand',
values: {
Blackberrys: 503,
Arrow: 175,
ParkAvenue: 358
}
}, {
label: 'Color',
name: 'color',
values: {
Black: 100,
Green: 200,
Red: 300
}
}]
function loadFilters() {
$scope.filters = filters.map(function(filter) {
var filter = angular.copy(filter);
for (var key in filter.values) {
filter.values[key] = {
selected: false,
count: filter.values[key]
}
}
return filter;
})
}
loadFilters();
Then you can call loadFilters() any time you want to clear all filters. Please see POC attached below.
https://plnkr.co/edit/SADPoUpftnJkg1rMuSB9?p=preview
You should try 'ng-change' on checkboxes to trigger a method which changes the values according to checked and unchecked checkboxes.
For Ex.
<input type="checkbox" ng-model='isSelected' ng-click='checkItem(key, k, isSelected)' ng-change="yourMethodHere()">
in JS:
$scope.yourMethodHere = function() {
if (isSelected) {
// filter the values here
} else {
// non filtered values
}
}
By doing this you do not need to even maintain the values of exiting checked/unchecked checkbox.

KO radio works but does not initialise as checked

Here's a snippet from a knockout based answer editor
<!-- ko foreach: Answers -->
<div class="qa-box" data-bindx="event: { mousedown: mouseDown, dragend: dragEnd, dragstart: dragStart }">
<div class="qa-body">
<div class="radio">
<label>
<input type="radio" data-bind="attr: { name: 'Q' + $parentContext.$index(), value: $index }, checked: $parent.CorrectAnswer" /><span></span>
Tick the correct answer
<span data-bind="text:$parent.CorrectAnswer"></span>
</label>
<a href="#" data-bind="click: $parent.remove.bind($parent)">
<i class="fa fa-times"></i>
Remove this answer
</a>
<div class="form-control" contenteditable="true" data-bind="ckeditor: $data, attr: { id: 'Q' + $parentContext.$index() + 'A' + $index() }"></div>
</div>
</div>
</div>
<!-- /ko -->
<div>CorrectAnswer: <span data-bind="text: CorrectAnswer"></span></div>
You'll notice I put a bound span on the end of the radio button label so I can see what happens to the CorrectAnswer observable when I interact with the UI. This is how I know it's correctly bound to the view model. Clicking a radio button or its label changes the value of CorrectAnswer exactly as intended.
This also allows me to know that CorrectAnswer contains the value I expected.
Let's take a closer look at the binding in case it isn't obvious.
attr: { name: 'Q'+$parentContext.$index(), value: $index }, checked: $parent.CorrectAnswer
All the answers for a given question get the same name Qx and a value provided by the item's list position. When an item is clicked its list position is written to CorrectAnswer. This does happen, as evidence by the new value showing up in the telltale div.
So, what could be preventing the UI from initialising as checked when everything else is fine?
It isn't an initialisation problem, it's a type compatibility problem. The value of a radio input is of type string. The value provided by my view model is of type number. Knockout does a strong comparison and does not recognise a match.
See also Radio buttons Knockoutjs

when i close the modal, checked inputs became unchecked

i use input with checkbox type to narrow my search result;
problem is i put the checkboxes in to the modal and when i checked many of them and close the modal the checked inputs become unchecked .
and i want every time that i open the modal input checked been checked.
var filterTemps = [
"partial/uicomponent/mdlFilters/mdl.estateType.filter.html",
];
$scope.showReleventMdl = function(num){
var filtersModal = $modal({
backdrop:true,
placement:'top',
templateUrl : filterTemps[num],
controller : 'filterCtrl',
show: false
});
filtersModal.$promise.then(filtersModal.show);
};
<!-- trigger the function for call modal -->
<ul class="nav navbar-nav">
<li>
</li>
...
</ul>
--------------------------------------------------
<!-- my Modal Template -->
<div class="modal-body">
<ul class="filterList">
<li class="filterListItem half" ng-repeat="item in string.pages.mainPage.estateTypes">
<input id="estateType{{$index}}" ng-click="checked(item)" type="checkbox" class="filterCheck">
<label for="estateType{{$index}}" ng-bind="item"></label>
</li>
</ul>
</div>
i want to know is there any way to store checked inputs and bring them back in checked state with modal ?
TNKS a lot
You are not setting any values to a $scope object. Try this...
<div class="modal-body">
<ul class="filterList">
<li class="filterListItem half" ng-repeat="item in string.pages.mainPage.estateTypes">
<input id="estateType{{$index}}" type="checkbox" ng-model="checkbox[$index].checked" class="filterCheck">
<label for="estateType{{$index}}" ng-bind="item"></label>
</li>
</ul>
</div>
Then, in your controller, you can set up the $scope object for your checkbox values.
$scope.checkbox = {};

JQuery conflict (maybe?) Hide/Show Div based on Radio Box

This is driving me crazy. I have tried every different ways to do this. Trying to show/hive a div based on a radio box selection. Below is my code into my main.js :
$("input[name='payment_method']").click(function () {
if ($(this).attr("id") == "payment_method_cod") {
$("#checkout_insurance").show();
} else {
$("#checkout_insurance").hide();
}
});
HTML:
<div id="checkout_insurance">
<h2>Checkout with Insurance</h2>
</div>
<div id="payment" class="woocommerce-checkout-payment">
<ul class="payment_methods methods">
<li class="payment_method_cod">
<input id="payment_method_cod" type="radio" class="input-radio" name="payment_method" value="cod" data-order_button_text="" checked="checked">
<label for="payment_method_cod">
...
</li>
<li class="payment_method_firstdata">
<input id="payment_method_firstdata" type="radio" class="input-radio" name="payment_method" value="firstdata" data-order_button_text="">
<label for="payment_method_firstdata">
....
</li>
</ul>
</div>
I cant get to work. If I place another cdn of the jQuery on the footer, the function works, however messes up a lot of other stuff. jQuery is being loaded on the header. I am current using jQuery 1.11.3.
Any help will be appreciated.
Thank you!
Use :checked selector to check if the radio element with id payment_method_cod is checked or not.
$('#payment_method_cod:checked') will return true/false based on the condition if the radio button is checked or not and toggle it, when true, the element #checkout_insurance will be shown.
Assuming the id's used in the code are unique.
Demo
$(document).on('change', "input[name='payment_method']", function() {
$("#checkout_insurance").toggle($('#payment_method_cod').is(':checked'));
}).trigger('change');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="checkout_insurance">
<h2>Checkout with Insurance</h2>
</div>
<div id="payment" class="woocommerce-checkout-payment">
<ul class="payment_methods methods">
<li class="payment_method_cod">
<input id="payment_method_cod" type="radio" class="input-radio" name="payment_method" value="cod" data-order_button_text="" checked="checked">
<label for="payment_method_cod">Payment</label>
...
</li>
<li class="payment_method_firstdata">
<input id="payment_method_firstdata" type="radio" class="input-radio" name="payment_method" value="firstdata" data-order_button_text="">
<label for="payment_method_firstdata">FirstData</label>
....
</li>
</ul>
</div>
$("input[name='payment_method']").change(function () {
if ($(this).attr("id") == "payment_method_cod" && $(this).is(':checked')) {
alert('show');
} else {
alert('hide');
}
});
Please use .change() on checkbox use .click() on button.
Try this approach this will select change event on checkbox and check if the id of the checkbox is payment_method_cod it will then show or hide depending on checked property
demo
Changing your code a bit :
$("input[name='payment_method']").click(function () {
var _this = $(this);
if (_this.val() == "cod") {
$("#checkout_insurance").show();
} else {
$("#checkout_insurance").hide();
}
});

Bind text input to value of observable array

I have an observable array that the user can add or remove items to. In addition I have one text input, and a DIV for each element in the array. When the user clicks on one of the DIVs I add the class "selected" to the DIV.
I want to bind the one input with the DIV that has the selected class.
Knockout:
self.tasks = ko.observableArray([]);
self.addTask = function() {
self.tasks.push(
{
id: "1",
content: ""
}
);
}
HTML:
<div data-bind="foreach: tasks">
<div class="wrapper" data-bind="text: content" class="selected"></div>
<div class="wrapper" data-bind="text: content"></div>
<div class="wrapper" data-bind="text: content"></div>
</div>
<label>Edit Task:</label> <input type="text" data-bind="value: content">
So basically every time one of the DIVs is selected I want to be able to updated the content parameter of the observable array that relates to the selected div, via the input field.
One way would be to create an observable that holds the index value of the selected task and bind your input accordingly:
<div data-bind="foreach: tasks">
<div class="wrapper" data-bind="text: content,
click: $root.selectTask,
css: {'selected': $root.selectedIndex() === $index()}">
</div>
</div>
<label>Edit Task:</label>
<input type="text" data-bind="value: tasks()[selectedIndex()].content">
You can see that the input value is bound to the content from one of the values in your tasks array. The selected class is also bound to that observable in a conditional.
Then your model would look like this (I defaulted the selectedIndex value to 0):
function Model() {
var self = this;
this.tasks = ko.observableArray();
this.addTask = function(id, content) {
self.tasks.push(
{
id: ko.observable(id),
content: ko.observable(content)
});
};
this.selectedIndex = ko.observable(0);
this.selectTask = function(task) {
self.selectedIndex(self.tasks.indexOf(task));
};
}
The selectTask function gets the new index based on where the user clicked and updates the observable. And all the DOM updating is taken care of for you after that.
Here's an example in jsFiddle: http://jsfiddle.net/MD35J/

Categories

Resources