Get checked attributes in recursive knockout - checkbox

I have a recursive dom in KnockoutJs:
<ul data-bind="template: { name: 'tree-hierarchy', foreach: someArray }"></ul>
<script id="some-tree" type="text/html">
<li>
<input type="checkbox" data-bind="attr: { id: id, name: name, value: value}, click: someFunc">
</li>
</scrpt>
I want to get the checked element's attributes so I use click functionality to get the data in the fucntion:
someFunc(data: any, event: any) {
//event.target gets me the attributes
}
I get the data I want in event.target, but immedialtly checked becomes unchecked.
If click functionality is not there, like this, checked remains:
<input type="checkbox" data-bind="attr: { id: id, name: name, value: value}>
The check remains, but when 'click' functionality calling the function is present, it unchecks immediately.
I want it to remain. I dont want to use 'checked: boolValue', functionality of knockout, since it is dynamically created and if there are 10 values in array, there would be 10 checbox inputs, hence having one bool value makes no sense.
I want checkbox to remain checked, after the call to function is completed.

Related

Using angularjs how can I get checked and unchecked values

Here I am binding values to ng-click as
<input type="checkbox" ng-model="a.CheckAssign"ng-click="myFunctionnew(a.ENQUIRY_CODE,a.CheckAssign)" />
enquiryArr=[]
$scope.myFunctionnew = function(enqcode,checkassign)
{
enquiryArr.push(enqcode + '&' + checkassign)
var uniqueNames = [];
$.each(enquiryArr, function (i, el) {
if ($.inArray(el, uniqueNames) === -1) {
uniqueNames.push(el);
console.log(uniqueNames)
}
else
{
console.log(uniqueNames);
}
}
Here when I check and uncheck the checkbox the value is storing multiple
Please help me how can I store Enquiry code and T/F values.
If I understand your issue correctly, you're running into duplicate entries in your enquiryArr. You're running into this because you're trying to manually keep track of the array in an odd fashion. While there are ways to correct the way you're storing it, it's even easier to have angular track what is checked and what is not.
Using the following DataSet:
$scope.enquiries = [
{ENQUIRY_CODE: 'ENQUIRY_1', ENQUIRY_NAME: 'First Enquiry', selected: false},
{ENQUIRY_CODE: 'ENQUIRY_2', ENQUIRY_NAME: 'Second Enquiry', selected: false},
{ENQUIRY_CODE: 'ENQUIRY_3', ENQUIRY_NAME: 'Third Enquiry', selected: false},
{ENQUIRY_CODE: 'ENQUIRY_4', ENQUIRY_NAME: 'Fourth Enquiry', selected: false}
];
And binding the selected field to your checkboxes ng-model
<div ng-repeat="e in enquiries">
<input type="checkbox" ng-model="e.selected" />
{{e.ENQUIRY_NAME}}
</div>
You can determine which one is checked simply by looking at the $scope.enquiries array and looking for selected: true (or false if you want to know the ones not checked).
In javascript you can use a simple Array Filter to get the selected values as such:
$scope.enquiries.filter(e => e.selected);
Or if you want to get them in your template, you can also use the filter pipe as such:
{{(enquiries | filter:{selected:true})}}
Here is an interactive plunkr that you can view this.
Misc Note: If you do want to run something when the checkbox is clicked, you can still use an ng-click and run your custom code, however, I would recommend using ng-change as there are other ways to change the selected value of a checkbox other than clicking.
I have test your code and its working fine. your problem is not so much clear so you can check following test code.
<div ng-controller="MyController">
<div ng-repeat="dt in data">
<input type="checkbox" ng-model="CheckAssign" ng-click="myFunctionnew(dt.name,dt.volume)" />
</div>
</div>
Javascript
$scope.myFunctionnew = function(enqcode,checkassign)
{
enquiryArr.push(enqcode + '&' + checkassign)
var uniqueNames = [];
for(i=0; i <enquiryArr.length; i++) {
if ($.inArray(enquiryArr[i], uniqueNames) == -1) {
uniqueNames.push(enquiryArr[i]);
console.log(uniqueNames)
}
else
{
console.log(uniqueNames);
}
}
}
JSFiddle

Vue JS for updating checkboxes based on radio selection

I basically have the same question as this guy, but using Vue JS instead of jQuery.
I have a list of N groups bound to my array ensemble_groups and represented by radio buttons. Selected value is mapped to selected_group.
I have a list of actors bound to my array cast with the variables actor_id, actor_name and groups. Each actor is pre-assigned to any number of groups. They're represented by checkboxes and mapped to an array visible_actors (when checked).
Here's my Vue JS powering the above data (I imagine the method is all jacked up, and I probably need a computed property of some sort):
new Vue({
el: '#schedule-builder',
data: {
selected_group: 'Entire Cast',
visible_actors: [],
ensemble_groups: [
"Entire Cast",
"Leads",
"Dancers",
"Children",
"Deselect All",
],
cast: [
{
actor_id: "123",
actor_name: "Carl",
groups: ["Entire Cast","Leads",],
},
{
actor_id: "234",
actor_name: "Max",
groups: ["Entire Cast","Leads","Children",],
},
{
actor_id: "345",
actor_name: "Sheryl",
groups: ["Entire Cast","Dancers",],
},
{
actor_id: "456",
actor_name: "Chip",
groups: ["Entire Cast","Children",],
},
],
},
methods: {
selectGroup: function() {
// uncheck all
visible_actors=[];
// add people in this group to visible_actors
for person in cast {
if (person.groups.indexOf(selected_group) > -1) {
visible_actors.push(person.actor_id);
}
}
}
})
When a user clicks on a radio button for a group, I want to select only the actors' checkboxes who are in that group. So if the user selects "Children", only the actors in the "Children" group should be checked (Max and Chip, per my example).
And, obviously, checking an actor (rather than a group) shouldn't affect the rest of the selections. I mention this because I got it partially working at one point, where selecting a group also selected the correct people, but when I clicked on a person suddenly everyone else was deselected. User can click either a group OR a person, and the expected behavior is that
Here's my HTML template:
<div id="schedule-builder">
<div class="select-groups">
<h3>Ensemble Groups</h3>
<template v-for="group in ensemble_groups">
<input name="select_group[]" id="group_#{{ $index }}"
v-model="selected_group"
:value="group"
#click="selectGroup"
type="radio">
<label for="group_#{{ $index }}">#{{ group }}</label>
</template>
</div>
<div class="select-individuals">
<h3>Cast Members</h3>
<template v-for="person in cast">
<input name="actors[]" id="actor-#{{ $index }}"
v-model="visible_actors"
:value="person.actor_id"
:checked="visible_actors.indexOf(person.actor_id) > -1"
type="checkbox">
<label for="actor-#{{ $index }}">
#{{ person.actor_name }}
</label>
</template>
</div>
</div>
Any help is appreciated... I've been banging my head on it for a couple days already.
This is a tough question to answer well but I'll try.
I would not rely on a computed property for the checked state. Let v-model handle that for you. You can do
<input
type="checkbox"
name="actors[]"
v-model="selected_actors"
:value="actor">
and that will manage the array of selected_actors for you as their values change.
I'm at work and plan on elaborating on this answer a little later but here's a fiddle of how I'd approach the situation: https://jsfiddle.net/crswll/806shzzg/7/

AngularJS - radio checked based on object value

What I'm trying to do is have a service (lets say: myService) that holds specific data like objects representing printers present and selected:
var localPrinters = [{ id: 12, name: 'HP', type: 'laser' },
{ id: 33, name: 'Lexmark', type: 'laser' }];
var activePrinter = {};
In some view that gets shown occasionally (like app settings), I have a controller that would define variables in the local scope which would point to the objects in the injected myService.
The view would then use ng-repeat to iterate over printer objects in localPrinters and display radio buttons that correspond to each object in the array..
Now i need two things..
1) update the activePrinter upon radiobutton selection change with the corresponding object value
2) in case the activePrinter already contains an object, when the view loads i want the corresponding radio to be checked already (if its value object matches the object in activePrinter, otherwise none should be selected.
I've managed 1) in a couple of ways.. either sticking to the model usage or adding methods to call upon ng-change.
//pseudocode
<container ng-repeat="printer in printers" >
<radio ng-value="printer" ng-model="$scope.activePrinter"/>
</container>
or
//pseudocode
<container ng-repeat="printer in printers" >
<radio ng-value="printer" ng-change="selectPrinter(printer)" "ng-model="$scope.activePrinter"/>
</container>
What i'm having trouble with is 2)
Not sure if there's a way in angular to automatically figure out some of the printer values matches the activePrinter selection and make the radio checked. Also not sure of the way i'm using ng-model for this purpose.
Any pointers?
Thanks!
You can do that in this way:
var app = angular.module('app', []);
app.controller('firstCtrl', function($scope) {
$scope.printers = [{
id: 12,
name: 'HP',
type: 'laser'
}, {
id: 33,
name: 'Lexmark',
type: 'laser'
}];
$scope.activePrinter = {};
//set default printer
$scope.activePrinter.printer = $scope.printers[0]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="app">
<div ng-controller="firstCtrl">
<div class="container" ng-repeat="printer in printers">
<label>{{printer.name}}</label>
<input type="radio" ng-value="printer" ng-model="activePrinter.printer" />
</div>
Active Printer:{{activePrinter.printer.id}} | {{activePrinter.printer.name}} | {{activePrinter.printer.type}}
</div>
</body>

Unselected radio button value in Angularjs

I've got an angularjs application that has a form/controller that look essentially like this (boiled down to the pertinent stuff):
angular.module('testApp', [])
.controller('testCtrl', function ($scope) {
$scope.envelopes = [{
id: 1,
name: 'first',
default_spend: '1'
}, {
id: 2,
name: 'second',
default_spend: '0'
}, {
id: 3,
name: 'third',
default_spend: '0'
}, ];
});
And a form that looks roughly like this:
<div ng-app="testApp">
<div ng-controller="testCtrl">
<div ng-repeat="envelope in envelopes">
<div>{{envelope.name}}
<input type="radio" name="default_spend" ng-model="envelope.default_spend" ng-value="1" />
Default Spend: {{envelope.default_spend}}
</div>
</div>
</div>
</div>
You can see this in action with this fiddle.
As you can see, the first envelope is marked as the default_spend envelope and the other two aren't. When I select a different envelope, that envelope also gets marked as the default_spend, but when the radio button is unselected, the model value stays the same ("1"). I understand that I'm dealing with a child scope here due to ng-repeat, but is there a way for me to set an "unselected" value without having to jump through hoops with ngChange?
Not really. When you use ng-value it is what is going to get bound to the ng-model and in your case all of them are having value 1. Also i really did not get the purpose of toggling 1 and 0, however you could just achieve it this way:-
<input type="radio" name="default_spend"
ng-click="selected.envelope = envelope" /> <!--Register an ng-click and set selected one
Default Spend: {{getDefSpend(envelope)}}</div> <!-- Show the text based on selection-->
And in your controller:-
$scope.selected = {envelope: $scope.envelopes[0]};
$scope.getDefSpend = function(envelope){
return $scope.selected.envelope === envelope ? 1 : 0;
}
//$scope.selected.envelope will be your selected option at any point.
Demo
It's because what you have is actually 3 different model values. To work as you want it, you would have ONE model value for all 3. You can either restructure your data, or use ng-change to modify your model manually.

ng-model on select stop working after typing in input

Right now selecting an option in the selectbox updates the input with the selected name, which is what I want. But if type something in the input field and then select another option in the selectbox it stops updating the input. How come?
Here is the code:
<div ng-app>
<div ng-controller="TestCtrl">
<select ng-model="selected" ng-options="box.name for box in selectBoxData">
</select>
<input type="text" name="newSelectValue" value="{{selected.name}}"/>
<button>Save</button>
</div>
function TestCtrl($scope)
{
$scope.selectBoxData = [
{ 'name': 'test1', 'id': 1 },
{ 'name': 'test2', 'id': 2 },
{ 'name': 'test3', 'id': 3 },
];
}
http://jsfiddle.net/C8hZN/
When you use {{selected.name}} in the value attribute of your input box, the value is linked to the selected object, but once you type into the input box, you modify the value so that it is disconnected it from the object reference. That is why future modifications to the select box no longer update the text box.
If you look at the value attribute in the console you'll see that it still updates correctly when the select changes. I think it doesn't display that value because whatever is typed into the box takes precedence over the attribute value.
To get around this I'd set a model on the text box and bind the selected option's name to that. Then when update is pressed, set the selected option's name from the input.
http://jsfiddle.net/C8hZN/3/

Resources