I'm trying to a checkbox and send the value YES or NO in my submitted form, base in if is checked or no but the value is not updated
here is my code:
self.checkbox = ko.observable("No");
self.is_checked = ko.computed({
read: function (data) {
return false;
},
write: function (data, event) { self.is_checked() ? self.checkbox('Yes'): self.checkbox('No');}
});
data-bind="checked: is_checked, checkedValue:checkbox"
any clues or links to read, please.
Your computed read function should return true or false so the UI is updated by the checked binding, and you can remove checkedValue entirely (checkedValue usually only makes sense to use with radio elements).
self.checkbox = ko.observable("No");
self.is_checked = ko.pureComputed({
read: () => self.checkbox() === "Yes",
write: (v) => self.checkbox(v ? "Yes" : "No")
})
data-bind="checked: is_checked"
Related
So I have two modals that I am using one of them was already implemented and behaves as expected however when I've added the other modal depending on the condition of if there is any true value when mapping over the array the way it works right now both modals show when there is a true value. I think this is because there are multiple false values returned from my .includes() function before the true appears. I think a good solution for this would be to make an array of all the values returned when I run .includes() on the entries then I can check that array for any true values but I cant seem to get the values into an array. When I try and push them into an array they just all push into their own separate arrays. This may be the wrong approach if it is can you explain what a better approach would be:
const checkPending = () => {
if(entries){
entries.map(descriptions => {
const desc = descriptions.description
//check if there are any pending tests
const check = desc.includes("pending")
//if the check returns true show the pending modal if it doesnt set the other modal to true
if(check === true){
setShowModal(false)
setShowPendingM(true)
}else{
setShowModal(true)
}
})
}
}
return(
<Button
onClick={() => checkPending()}
className={`${styles.headerButton} mr-2`}
>
Add File
<Plus />
</Button>
)
setShowModal & setShowPendingM are both passed from a parent component as props. They are both initialized as false. The most straightforward question I can pose is is there any way to say if there are any true values returned from .includes then do something even if there are false values present
I think this is how your checkingPending method should look like.
const checkPending = () => {
if(entries){
let pending = false;
entries.forEach((descriptions) => {
const desc = descriptions.description
if(desc.includes('pending')){
pending = true;
}
});
if(pending) {
setShowModal(false);
setShowPendingM(true);
} else {
setShowModal(true);
setShowPendingM(false);
}
}
}
Let me know if you have any additional questions.
I have a long set of checkboxes. I would like two groups of three of them to behave as radio buttons. Now, leaving aside my UX choices, how can I make this work?
The checkboxes are implemented as properties on a single object, layer:
data() {
return {
layer: {},
}
},
watch: {
layer: {
handler(val, oldval) {
mapping.updateLayers(val)
},
deep: true,
},
},
That works fine. But intercepting val and updating this.layer inside handler() doesn't:
handler: function(val, oldval) {
if (val.FutureYear) { this.layer.NextYear = false; this.layer.ExistingYear = false; }
if (val.ExistingYear) { this.layer.NextYear = false; this.layer.FutureYear = false; }
if (val.NextYear) { this.layer.ExistingYear = false; this.layer.FutureYear = false; }
mapping.updateFoiLayers(val);
},
How can I achieve this result? (I'd prefer not to have to implement actual radio buttons because that makes managing all the layers and UI more complex.)
Example: https://codepen.io/jacobgoh101/pen/NyRJLW?editors=0010
The main problem is the logic in watch.
If FutureYear is selected already, other field becomes unchangeable. Because if (val.FutureYear) is always the first one being triggered and the other 2 field will always be set to false immediately.
Another thing about watch is that it will be triggered when
user changed the value
program changed the value (this is unnecessary and make things harder to handle)
Therefore, handling #change event is more appropriate in this scenario.
JS
methods: {
handleChange: function(e) {
const name = e.target.name;
if (this.layer[name]) {
Object.keys(this.layer).map((key)=>{
if(key != name) {
this.layer[key] = false;
}
})
}
}
}
html
<div id="app">
<input type="checkbox"/ v-model="layer.FutureYear" name="FutureYear" #change="handleChange($event)">FutureYear<br/>
<input type="checkbox"/ v-model="layer.NextYear" name="NextYear" #change="handleChange($event)">NextYear<br/>
<input type="checkbox"/ v-model="layer.ExistingYear" name="ExistingYear" #change="handleChange($event)">ExistingYear<br/>
</div>
I want to detect when a user has entered values into any form field by using the $dirty property and setting a flag accordingly. Not surprisingly, this works:
$scope.$watch('formDetails.$dirty', function() {
USR.userInputRecorded = true;
});
But I'd also like to detect when/if the user has emptied all fields and effectively restored the form to its original empty state. The snippet below does not work and I'm not sure why. Is there a way to watch for when the form changes back to "not dirty"?
$scope.$watch('formDetails.$pristine', function() {
USR.userInputRecorded = false;
});
Thanks.
Try this:
$scope.$watch('formDetails.$dirty', function(value) {
if (value === '') {
// field has been emptied;
your.form.$setPristine(true);
} else {
USR.userInputRecorded = true;
}
});
I have this checkbox
<input type="checkbox"
ng-change="defaultMsgsHandler(vuser.use_managed_default_msgs)"
ng-model="vuser.use_managed_default_msgs"
ng-true-value=1 ng-false-value=0>
When i make this ajax call, the checkbox does not reflect the ajax retured has vuser.use_managed_default_msgs set to 1, but the checkbox is not checked. I know the model is correct. vuser.use_managed_default_msgs is a 1 if i dump vuser to the console.
messageServices.getMessageSettingsInfo(user.dir)
.then(function(data) {
if (!data.success) {
$scope.errormessage = data.errors;
} else {
$scope.vuser = data.vuser;
$scope.messages = data.messages;
}
}, function(error) {
alert(error);
});
If i click on the checkbox defaultMsgsHandler changed the model correctly, and the checkbox checks and unchecks.
$scope.defaultMsgsHandler = function( use_managed_default_msgs ){
$scope.vuser.use_managed_default_msgs = use_managed_default_msgs;
};
Thanks for any help
Please, try to use: ng-checked="condition"
There is a similar question here,
How to set checkbox selected on the basis of model value
Not sure if it will help, but I think your
ng-true-value=1 ng-false-value=0
should be
ng-true-value="1" ng-false-value="0"
I been trying to do checkbox Checkall and UnCheckall using subscribe and i'm partially successful doing that but i am unable to find a fix in couple of scenarios when i am dealing with subscribe .
Using subscribe :
I am here able to checkAll uncheckAll but when i uncheck a child checkbox i.e test1 or test2 i need my parent checkbox name also to be unchecked and in next turn if i check test1 the parent checkbox should be checked i.e keeping condition both child checkboxes are checked .
For fiddle : Click Here
ViewModel :
self.selectedAllBox.subscribe(function (newValue) {
if (newValue == true) {
ko.utils.arrayForEach(self.People(), function (item) {
item.sel(true);
});
} else {
ko.utils.arrayForEach(self.People(), function (item) {
item.sel(false);
});
}
});
The same scenario can be done perfectly in easy way using computed but due some performance issues i need to use subscribe which is best way it wont fire like computed onload .
Reference : Using computed same thing is done perfectly check this Fiddle
I tried to use change event in individual checkbox binding but its a dead end till now.
Any help is appreciated .
Your subscription only applies to edits on the selectedAllBox. To do what you want, you'll need subscriptions on every Person checkbox as well, to check for the right conditions and uncheck the selectedAllBox in the right situations there.
It strikes me as odd that this would be acceptable but using computed() is not. Maybe you should reconsider that part of your answer. I would much rather compute a "isAllSelected" value based on my viewModel state, then bind the selectedAllBox to that.
I solved a similar problem in my own application a couple of years ago using manual subscriptions. Although the computed observable method is concise and easy to understand, it suffers from poor performance when there's a large number of items. Hopefully the code below speaks for itself:
function unsetCount(array, propName) {
// When an item is added to the array, set up a manual subscription
function addItem(item) {
var previousValue = !!item[propName]();
item[propName]._unsetSubscription = item[propName].subscribe(function (latestValue) {
latestValue = !!latestValue;
if (latestValue !== previousValue) {
previousValue = latestValue;
unsetCount(unsetCount() + (latestValue ? -1 : 1));
}
});
return previousValue;
}
// When an item is removed from the array, dispose the subscription
function removeItem(item) {
item[propName]._unsetSubscription.dispose();
return !!item[propName]();
}
// Initialize
var tempUnsetCount = 0;
ko.utils.arrayForEach(array(), function (item) {
if (!addItem(item)) {
tempUnsetCount++;
}
});
var unsetCount = ko.observable(tempUnsetCount);
// Subscribe to array changes
array.subscribe(function (changes) {
var tempUnsetCount = unsetCount();
ko.utils.arrayForEach(changes, function (change) {
if (change.moved === undefined) {
if (change.status === 'added') {
if (!addItem(change.value))
tempUnsetCount++;
} else {
if (!removeItem(change.value))
tempUnsetCount--;
}
}
});
unsetCount(tempUnsetCount);
}, null, 'arrayChange');
return unsetCount;
}
You'll still use a computed observable in your viewmodel for the the select-all value, but now it'll only need to check the unselected count:
self.unselectedPeopleCount = unsetCount(self.People, 'Selected');
self.SelectAll = ko.pureComputed({
read: function() {
return self.People().length && self.unselectedPeopleCount() === 0;
},
write: function(value) {
ko.utils.arrayForEach(self.People(), function (person) {
person.Selected(value);
});
}
}).extend({rateLimit:0});
Example: http://jsfiddle.net/mbest/dwnv81j0/
The computed approach is the right way to do this. You can improve some performance issues by using pureComputed and by using rateLimit. Both require more recent versions of Knockout than the 2.2.1 used in your example (3.2 and 3.1, respectively).
self.SelectAll = ko.pureComputed({
read: function() {
var item = ko.utils.arrayFirst(self.People(), function(item) {
return !item.Selected();
});
return item == null;
},
write: function(value) {
ko.utils.arrayForEach(self.People(), function (person) {
person.Selected(value);
});
}
}).extend({rateLimit:1});
http://jsfiddle.net/mbest/AneL9/98/