Angular ng-if not responding as expected - javascript

I have li elements that have an ng-if statement that is tied to a checkbox. If I physically check the checkbox, the ng-if responds as expected. However, if I check or uncheck the checkbox via JavaScript, the checkboxes get checked or unchecked as expected, but the ng-if does not respond. Is this working as it should? Is there a better way to do this?
Here are my code samples: "[]" = "<>"
HTML - Part 1
[li id="homebutton" ng-if="homechecked != true" onclick="homeclicked()"][a ng-href="/"][img src="images\Neck01Home.png" alt="Home" /][/a]
[li id="thebandbutton" ng-if="homechecked===true" onclick="thebandclicked()"][a ng-href="/theband/"][img src="images\Neck01TheBand.png" alt="The Band" /][/a]
HTML - Part 2
[label class="menucontroller"]Home2: [input class="menucontroller" id="homecb" type="checkbox" ng-model="homechecked" ng-init="homechecked=true" /][/label][br /]
[label class="menucontroller"]TheBand2: [input class="menucontroller" id="bandcb" type="checkbox" ng-model="thebandchecked" /][/labe][
[label class="menucontroller"]Gallery2: [input class="menucontroller" id="gallerycb" type="checkbox" ng-model="gallerychecked" /][/label][br /]
JavaScript:
window.onload = function () {
}
function homeclicked() {
document.getElementById('homecb').checked = true;
document.getElementById('bandcb').checked = false;
document.getElementById('gallerycb').checked = false;
}
function thebandclicked() {
document.getElementById('homecb').checked = false;
document.getElementById('bandcb').checked = true;
document.getElementById('gallerycb').checked = false;
}
function galleryclicked() {
document.getElementById('homecb').checked = false;
document.getElementById('bandcb').checked = false;
document.getElementById('gallerycb').checked = true
}

you're doing it wrong, ng-if does not trigger because you only manipulate the checked and unchecked of the check box(using javascript) and not the ng-model, dont try to use javascript to do that, instead do it on your angular controller.
Controller:
$scope.homeclicked = function() {
$scope.homechecked = true;
$scope.thebandchecked = false;
$scope.gallerychecked = false;
};
ng-model on checkbox inputs handles checked and unchecked of it, also there is a native directive https://docs.angularjs.org/api/ng/directive/ngChecked for handling of check and uncheck.

Do it in proper angular way.
Move the functions inside your controller. Call them via ng-click. Let the functions change the scope variables which are bound to check boxes.
<li id="homebutton" ng-if="homechecked != true" ng-click="homeclicked()">
In the mean time inside your scope...
$scope.homeclicked = function {
$scope.homechecked = true;
$scope.thebandchecked = false;
$scope.gallerychecked = false;
}
If you really really want to disregard my advice and go ahead with what you have, which is by the way very bad, you can add this line inside your functions: angular.element(document.getElementById('homecb')).$scope().$apply(); This is again very bad and should totally be avoided.

Use
$scope.$apply();
It will run the digest loop and your ng-if will work as u expect.

Related

Is there any way to check whether form is dirty or not in JavaScript?

I have one form validator example in java script. In this case, Is there any way to check whether the form is dirty or not?
My platform is JavaScript
Please find corresponding sample below, and suggest any solution.
sample link
code snipet:
i have used like:
if (name.value != name.defaultValue) {
alert("#name has changed");
}
you have tags as kendo-ui-grid and kendo-validator so I suppose you are using kendo framework.
if you want to see if the form is dirty you should check the viewModel in kendo way sample.
basically I've created a viewModel which is impements the ObservableObject interface and has a two way binding with the form's container.
Every time you change something in the form the change event is fired in the viewModel which set a variable (dirty) as true.
var dirty = false;
var viewModel = new kendo.data.ObservableObject({
fullname: "test"
});
viewModel.bind("change", function () {
alert("changed");
dirty = true;
});
kendo.bind($("#tickets"), viewModel);
Add all the fields you need to "watch" in the ObservableObject
and set on their markup the property data-bind="value:fieldName"
You could use JQuery something like this...
var _isDirty = false;
$("input[type='text']").change(function(){
_isDirty = true;
});
You need a global boolean variable to remember when you edit anything in your form.
This variable should initially be false, then when the user edits an input, it changes to true. When you submit the form it changes back to false. Now you can check any time you want, whether the dirty variable is true or false.
Example code:
var dirty = false;
var inputs = document.querySelectorAll('input');
for (var i = 0;i < inputs.length)
{
var input = inputs[i];
input .addEventListener('input', function()
{
dirty = true;
});
}
var form = document.forms[0];
form.addEventListener('submit, function()
{
dirty = false;
}

How to change x-editable event order?

I'm using angularJs and xeditables to create a web application.
In this application, I have several xeditable text following each others and the validation is done when pressing enter or clicking outside:
<div ng-repeat="answer in item.answers track by $index">
<input type="radio" name="{{item.label.text}}"> <span editable-text="answer.text" onshow="onShow()" onhide="onClose()" buttons="no" blur="submit" onbeforesave="validateEditableText($data)">{{answer.text || "Edit this text"}}</span>
</div>
My functions onShow() and onClose() are the following :
$scope.onShow = function() {
alert('onShow');
if($scope.hideMenu == true)
$scope.hideMenu = false;
};
$scope.onClose = function() {
alert('onClose');
if($scope.hideMenu == false)
$scope.hideMenu = true;
};
These functions are just changing a boolean to true.
I use this boolean to stop or not the event propagation (It may sounds weird but I need this functionality).
Here is my function which block the event propagation but it won't be necessary for you to fully understand it for the explications:
$scope.blocEventPropagation = function(event) {
if($scope.selectedItem != null){
if($scope.hideMenu && !$scope.selectedItem.dropDownOpen)
event.stopPropagation();
}
};
Actually the problem I have is, when I click on a xeditable text and then I click directly on another the events don't follow the order I want.
The order is onShow() of the first xeditable text when I click on it, onShow() of the second when I directly click on it before closing the other and onClose() of the first.
Me I'd like onShow() of the first when I click on it, onClose() on the first when I click a second one and onShow() of the second.
At this point read all the documentation of xeditable and I didn't found a solution. I tried to use a time-out to wait the other event but it didn't work.
Do you have an idea to change the event order or to limit the call of a function or even another solution that I didn't think about ?
You can have all elements give a separate contribution in hiding the menu:
<div ng-repeat="answer in item.answers track by $index">
<input type="radio" name="{{item.label.text}}"> <span editable-text="answer.text" onshow="{{$scope.hideMenu[$index] = true;}}" onhide="{{$scope.hideMenu[$index] = false;}}" buttons="no" blur="submit" onbeforesave="validateEditableText($data)">{{answer.text || "Edit this text"}}</span>
</div>
And then, hide it if any element is shown:
<div id="menu" ng-hide="{{$scope.hideMenu.indexOf(true) >= 0}}" />
There may be syntax errors, but I hope it clarifies the point.
Finally I found a solution :
$scope.count = 0;
$scope.onShow = function() {
$scope.count ++;
if($scope.hideMenu == true)
$scope.hideMenu = false;
};
$scope.onClose = function() {
$scope.count --;
if($scope.hideMenu == false && $scope.count == 0)
$scope.hideMenu = true;
};
This solution is very ugly but I really think that with my actual knowledge its the better one in this very specific situation. I tried to find a better one but I couldn't.
Indeed, the previous answer works if we use onShow() and onClose() inside a ng-repeat with the $index. But me I use these two functions at different places in my application so I can't have an index.

Need to run a function based on conditional

I'm trying to assign a function to a couple of checkboxes, but I only want them added based on a condition, in this case the step number of the form. This is a roundabout way of making the checkboxes readOnly AFTER they have been selected (or not). So, at step 1 I want the user to choose cb1 or cb2, but at step 2 I want to assign the function that will not let the checkboxes values be changed.
What am I doing wrong?
function functionOne() {
this.checked = !this.checked
};
if (document.getElementById("stepNumber").value == 2) {
document.getElementById("cb1").setAttribute("onkeydown", "functionOne(this)");
document.getElementById("cb2").setAttribute("onkeydown", "functionOne(this)");
}
You are passing the element in an argument, so use that:
function functionOne(elem) {
elem.checked = !elem.checked
};
You could also use properties:
document.getElementById("cb1").onkeydown = functionOne;
document.getElementById("cb2").onkeydown = functionOne;
function functionOne() {
this.checked = !this.checked
};
This is a solution that requires jquery but you can use the .click function to disable checkboxes once one is clicked.
Here is a working example:
http://jsfiddle.net/uPsm7/
Why not on the selection disable the checkbox?
Function onCheck(elm)
{
document.getElementById("cbValue").value = elm.value;
elm.disabled = true;
}
<input id="cbValue" type="hidden" />
Use the hidden input field to allow form to send data back to server.

If is a checkbox Checked do

i have an issue.
I'm trying avoid the user leaves the page if theres any element checked.
For instance, i have several checkboxes with a class named "testCheckbox" and i tried that:
window.onbeforeunload = function(){
if($('.testCheckbox').attr('checked'))
return 'yes';
else
return 'no';}}
But it always is says 'yes' when the first checkbox (in order of appear) is checked, if i check the second or the third, etc, says 'no'.
You can use checked-selector along with with is
if ($('.testCheckbox').is(':checked'))
if ($('.testCheckbox:checked').length)
your probably wanting to do something like this
window.onbeforeunload = function()
{
var yesno = 'no';
$('.testCheckbox').each(function(index,value){
if($(value).attr('checked'))
{
yesno = 'yes';
return false;
}
});
return yesno;
}

Check/Uncheck checkbox with JavaScript

How can a checkbox be checked/unchecked using JavaScript?
Javascript:
// Check
document.getElementById("checkbox").checked = true;
// Uncheck
document.getElementById("checkbox").checked = false;
jQuery (1.6+):
// Check
$("#checkbox").prop("checked", true);
// Uncheck
$("#checkbox").prop("checked", false);
jQuery (1.5-):
// Check
$("#checkbox").attr("checked", true);
// Uncheck
$("#checkbox").attr("checked", false);
Important behaviour that has not yet been mentioned:
Programmatically setting the checked attribute, does not fire the change event of the checkbox.
See for yourself in this fiddle:
http://jsfiddle.net/fjaeger/L9z9t04p/4/
(Fiddle tested in Chrome 46, Firefox 41 and IE 11)
The click() method
Some day you might find yourself writing code, which relies on the event being fired. To make sure the event fires, call the click() method of the checkbox element, like this:
document.getElementById('checkbox').click();
However, this toggles the checked status of the checkbox, instead of specifically setting it to true or false. Remember that the change event should only fire, when the checked attribute actually changes.
It also applies to the jQuery way: setting the attribute using prop or attr, does not fire the change event.
Setting checked to a specific value
You could test the checked attribute, before calling the click() method. Example:
function toggle(checked) {
var elm = document.getElementById('checkbox');
if (checked != elm.checked) {
elm.click();
}
}
Read more about the click method here:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click
to check:
document.getElementById("id-of-checkbox").checked = true;
to uncheck:
document.getElementById("id-of-checkbox").checked = false;
We can checked a particulate checkbox as,
$('id of the checkbox')[0].checked = true
and uncheck by ,
$('id of the checkbox')[0].checked = false
Try This:
//Check
document.getElementById('checkbox').setAttribute('checked', 'checked');
//UnCheck
document.getElementById('chk').removeAttribute('checked');
I would like to note, that setting the 'checked' attribute to a non-empty string leads to a checked box.
So if you set the 'checked' attribute to "false", the checkbox will be checked. I had to set the value to the empty string, null or the boolean value false in order to make sure the checkbox was not checked.
Using vanilla js:
//for one element:
document.querySelector('.myCheckBox').checked = true //will select the first matched element
document.querySelector('.myCheckBox').checked = false//will unselect the first matched element
//for multiple elements:
for (const checkbox of document.querySelectorAll('.myCheckBox')) {
//iterating over all matched elements
checkbox.checked = true //for selection
checkbox.checked = false //for unselection
}
function setCheckboxValue(checkbox,value) {
if (checkbox.checked!=value)
checkbox.click();
}
<script type="text/javascript">
$(document).ready(function () {
$('.selecctall').click(function (event) {
if (this.checked) {
$('.checkbox1').each(function () {
this.checked = true;
});
} else {
$('.checkbox1').each(function () {
this.checked = false;
});
}
});
});
</script>
For single check try
myCheckBox.checked=1
<input type="checkbox" id="myCheckBox"> Call to her
for multi try
document.querySelectorAll('.imChecked').forEach(c=> c.checked=1)
Buy wine: <input type="checkbox" class="imChecked"><br>
Play smooth-jazz music: <input type="checkbox"><br>
Shave: <input type="checkbox" class="imChecked"><br>
If, for some reason, you don't want to (or can't) run a .click() on the checkbox element, you can simply change its value directly via its .checked property (an IDL attribute of <input type="checkbox">).
Note that doing so does not fire the normally related event (change) so you'll need to manually fire it to have a complete solution that works with any related event handlers.
Here's a functional example in raw javascript (ES6):
class ButtonCheck {
constructor() {
let ourCheckBox = null;
this.ourCheckBox = document.querySelector('#checkboxID');
let checkBoxButton = null;
this.checkBoxButton = document.querySelector('#checkboxID+button[aria-label="checkboxID"]');
let checkEvent = new Event('change');
this.checkBoxButton.addEventListener('click', function() {
let checkBox = this.ourCheckBox;
//toggle the checkbox: invert its state!
checkBox.checked = !checkBox.checked;
//let other things know the checkbox changed
checkBox.dispatchEvent(checkEvent);
}.bind(this), true);
this.eventHandler = function(e) {
document.querySelector('.checkboxfeedback').insertAdjacentHTML('beforeend', '<br />Event occurred on checkbox! Type: ' + e.type + ' checkbox state now: ' + this.ourCheckBox.checked);
}
//demonstration: we will see change events regardless of whether the checkbox is clicked or the button
this.ourCheckBox.addEventListener('change', function(e) {
this.eventHandler(e);
}.bind(this), true);
//demonstration: if we bind a click handler only to the checkbox, we only see clicks from the checkbox
this.ourCheckBox.addEventListener('click', function(e) {
this.eventHandler(e);
}.bind(this), true);
}
}
var init = function() {
const checkIt = new ButtonCheck();
}
if (document.readyState != 'loading') {
init;
} else {
document.addEventListener('DOMContentLoaded', init);
}
<input type="checkbox" id="checkboxID" />
<button aria-label="checkboxID">Change the checkbox!</button>
<div class="checkboxfeedback">No changes yet!</div>
If you run this and click on both the checkbox and the button you should get a sense of how this works.
Note that I used document.querySelector for brevity/simplicity, but this could easily be built out to either have a given ID passed to the constructor, or it could apply to all buttons that act as aria-labels for a checkbox (note that I didn't bother setting an id on the button and giving the checkbox an aria-labelledby, which should be done if using this method) or any number of other ways to expand this. The last two addEventListeners are just to demo how it works.
I agree with the current answers, but in my case it does not work, I hope this code help someone in the future:
// check
$('#checkbox_id').click()

Categories

Resources