ng-disabled in angularjs is not working for me - angularjs

I'm trying to enable and disable the button using some condition
I am able to disable the button using $scope.isDisabled = true; , but can't enable the button
Here is my code
HTML file
<input type="submit" value="Continue" ng-model="isDisabled" ng-disabled="isDisabled">
Controller JS file
$scope.isDisabled = true; // here the button disabled (for me)
if (count >= 3) { // it's always true
$scope.isDisabled = false; // try to enable the button here
}

Do not use $scope.apply. That is not what it is meant for.
The button does not need to be bound to a model, try removing the ng-model from the button.
Also, if it is an input type of "submit" and you are not inside an ng-form, that might
cause a postback and you might lose your state.
Here is a plunk that shows it working - i made some assumptions to get the plunk going. added an extra button that triggered the count increments.
http://plnkr.co/edit/QGYMqGHCKUoDGaY9WYhj?p=preview

Related

Prevent check of checkbox until function has been called

We are using AngularJS, and we require to run a function that determines whether or not the checkbox the user clicked on is actually checked. I have tried to pass $event on ngChange, but discovered it is unable to pass the $event object. The reason I want to access the $event object is so I could prevent the default behaviour until the required function has been called.
The code is as follows (does not include the code where I attempted to pass $event as it didn't work):
<label for="specificCase">
Yes
<input
type="checkbox"
name="specificCase"
data-ng-click="specificCase.no = false; specificCase.unsure = false;"
data-ng-model="specificCase.yes"
data-ng-change="$ctrl.specificCaseCheck('yes', specificCase.yes)">
</label>
<label for="notSpecificCase">
No
<input
type="checkbox"
name="notSpecificCase"
data-ng-click="specificCase.yes = false; specificCase.unsure = false;"
data-ng-model="specificCase.no"
data-ng-change="$ctrl.specificCaseCheck('no', specificCase.no)">
</label>
controller
function specificCaseCheck(value, boolean) {
//HERE I WANT TO PREVENT THE DEFAULT BEHAVIOUR OF THE CHECKBOX CHECKING
vm.optionSelected = !boolean ? false : true;
vm.caseSpecific = value == 'yes' && boolean ? true : false;
}
Question
How do I keep the checkbox unchecked until I have run a function in the controller?
Since you need to prevent default behavior but dont have the event you can follow the approach of this question Angular 2 Checkbox preventDefault
Basically you need to return false in your event handler to prevent the default behavior of "checking the checkbox when is clicked" then you can click it programatically
For that you can check this question Angular 4 checkbox set programmatically

How to target an element when navigating to another page (partial)

I have a checkbox that I'd like to set the indeterminate state to based on the states of other checkboxes. When I'm on the page that the checkboxes are all in, it updates as expected (i.e. the checkbox is found). But when I navigate to that from another page, my method does not find the checkbox (i.e. returns null).
When I debug in Chrome devtools, I notice
let checkBoxWithIndeterminateState;
let checkbox = false;
fireWhenCheckBoxChanged() {
// returns null when navigating from another page but not when on its own page
checkBoxWithIndeterminateState = document.getElementById('checkBoxWithIndeterminateState')
checkBoxWithIndeterminateState.indeterminate = true
}
Template:
<input type="checkbox" id="checkBoxWithIndeterminateState" data-ng-model="checkbox">
How do I wait until the new template has loaded before my method tries to find the checkbox? I've read some suggestions to use this._$scope.$on('$viewContentLoaded'... but this doesn't work.
Thanks!
What about adding an ng-init directive to your target checkbox and do your logic in it, this way you are sure the element is there, here is a suggestion:
<input type="checkbox" ng-init="initTragetCheckbox()">
In your controller
$scope.initTragetCheckbox = function () {
// your code to execute for other checkboxes
var checkbox1 = document.getElementById("checkbox1");
var checkbox2 = document.getElementById("checkbox2");
....
}

Hide button after ng-click using AngularJS

I'm new to angularjs and wanted to know how to hide a button after clicking (using ng-click) on it.
<button ng-click="xyz()" class="btn-default pull-right">
Start
</button>
Basically, you needs two things:
A variable leveraging the button visibility
A function to update this variable (you could do it in the HTML but I discourage it).
So you would have your button:
<button ng-click="hideButton()" ng-show="isButtonVisible === true" class="btn-default pull-right">
Start
</button>
Then, you would have the following variables
$scope.isButtonVisible = true; // true to make the button visible by default
And finally, the function that toggles it:
$scope.hideButton = function() {
$scope.isButtonVisible = false;
}
Note that you could use ng-if to remove the button from the DOM if you won't need it again.
Example: https://plnkr.co/edit/fnW8HR58zKHs4T34XRan
Note that this is pretty much the most basic question you could have on AngularJS, so I would advice you to read a bit about it before asking Stack Overflow.
You will need a variable to denote the visibility of the button, its value will change with click event.
<button ng-click="clickEventFunction(params)" ng-hide="isButtonVissible">Button</button>
The default value of this variable should be "false" to show the button
$scope.isButtonVissible = false
Then in the clickEventFunction, change the value to hide the button
$scope.clickEventFunction = function(params){
$scope.isButtonVissible = true;
//* Do the logic code
}
I found the answer to the question with some assistance. Created an event in the click function and was able to hide the button.
<button ng-click="xyz($event)" class="btn-default pull-right">Start</button>
$scope.xyz = function ($event) {
$($event.target).hide();
Cheers to all your guidance.
In View:
<button ng-click="hideBtn = true" ng-hide="hideBtn">Button</button>
In controller :
$scope.hideBtn = false;

how to toggle medium editor option on click using angularjs

I am trying to toggle the medium editor option (disableEditing) on button click. On the click the value for the medium editor option is changed but the medium editor does not use 'updated' value.
AngularJS Controller
angular.module('myApp').controller('MyCtrl',
function MyCtrl($scope) {
$scope.isDisableEdit = false;
});
Html Template
<div ng-app='myApp' ng-controller="MyCtrl">
<span class='position-left' medium-editor ng-model='editModel' bind-options="{'disableEditing': isDisableEdit, 'placeholder': {'text': 'type here'}}"></span>
<button class='position-right' ng-click='isDisableEdit = !isDisableEdit'>
Click to Toggle Editing
</button>
<span class='position-right'>
toggle value - {{isDisableEdit}}
</span>
</div>
I have created a jsfiddle demo.
I think initialising medium editor on 'click' could solve the issue, but i am not sure how to do that either.
using thijsw angular medium editor and yabwe medium editor
For this specific use case, you could try just disabling/enabling the editor when the button is clicked:
var editor = new MediumEditor(iElement);
function onClick(event) {
if (editor.isActive) {
editor.destroy();
} else {
editor.setup();
}
}
In the above example, the onClick function is a handler for that toggle button you defined.
If you're just trying to enable/disable the user's ability to edit, I think those helpers should work for you.
MediumEditor does not currently support changing configuration options on an already existing instance. So, if you were actually trying to change a value for a MediumEditor option (ie disableEditing) you would need to .destroy() the previous instance, and create a new instance of the editor:
var editor = new MediumEditor(iElement),
editingAllowed = true;
function onClick(event) {
editor.destroy();
if (editingAllowed) {
editor = new MediumEditor(iElement, { disableEditing: true });
} else {
editor = new MediumEditor(iElement);
}
editingAllowed = !editingAllowed;
}
Once instantiated, you can use .setup() and .destroy() helper methods to tear-down and re-initialize the editor respectively. However, you cannot pass new options unless you create a new instance of the editor itself.
One last note, you were calling the init() method above. This method is not officially supported or documented and it may be going away in future releases, so I would definitely avoid calling that method if you can.
Or you could just use this dirty hack : duplicate the medium-editor element (one with disableEditing enabled, the other with disableEditing disabled), and show only one at a time with ng-show / ng-hide :)
<span ng-show='isDisableEdit' class='position-left' medium-editor ng-model='editModel' bind-options="{'disableEditing': true ,'disableReturn': isDisableEdit, 'placeholder': {'text': 'type here'}}"></span>
<span ng-hide='isDisableEdit' class='position-left' medium-editor ng-model='editModel' bind-options="{'disableEditing':false ,'disableReturn': isDisableEdit, 'placeholder': {'text': 'type here'}}"></span>
You can see jsfiddle.

Why is my click event called twice in jquery?

Why is my click event fired twice in jquery?
HTML
<ul class=submenu>
<li><label for=toggle><input id=toggle type=checkbox checked>Show</label></li>
</ul>
Javascript
$("ul.submenu li:contains('Show')").on("click", function(e) {
console.log("toggle");
if ($(this).find("[type=checkbox]").is(":checked")) console.log("Show");
else console.log("Hide");
});
This is what I get in console:
toggle menu.js:39
Show menu.js:40
toggle menu.js:39
Hide menu.js:41
> $("ul.submenu li:contains('Show')")
[<li>​ ]
<label for=​"toggle">​
<input id=​"toggle" type=​"checkbox" checked>​
"Show"
</label>​
</li>​
If I remember correctly, I've seen this behavior on at least some browsers, where clicking the label both triggers a click on the label and on the input.
So if you ignore the events where e.target.tagName is "LABEL", you'll just get the one event. At least, that's what I get in my tests:
Example with both events | Source
Example filtering out the e.target.tagName = "LABEL" ones | Source
I recommend you use the change event on the input[type="checkbox"] which will only be triggered once. So as a solution to the above problem you might do the following:
$("#toggle").on("change", function(e) {
if ($(this).is(":checked"))
console.log("toggle: Show");
else
console.log("toggle: Hide");
});
https://jsfiddle.net/ssrboq3w/
The vanilla JS version using querySelector which isn't compatible with older versions of IE:
document.querySelector('#toggle').addEventListener('change',function(){
if(this.checked)
console.log('toggle: Show');
else
console.log('toggle: Hide');
});
https://jsfiddle.net/rp6vsyh6/
This behavior occurs when the input tag is structured within the label tag:
<label for="toggle"><input id="toggle" type="checkbox" checked>Show</label>
If the input checkbox is placed outside label, with the use of the id and for attributes, the multiple firing of the click event will not occur:
<label for="toggle">Show</label>
<input id="toggle" type="checkbox" checked>
I found that when I had the click (or change) event defined in a location in the code that was called multiple times, this issue occurred. Move definition to click event to document ready and you should be all set.
Not sure why this wasn't mentioned. But if:
You don't want to move the input outside of the label (possibly because you don't want to alter the HTML).
Checking by e.target.tagName or even e.target doesn't work for
you because you have other elements inside the label
(in my case it had spans holding an SVG with a path so e.target.tagName sometimes showed SVG and other times it showed PATH).
You want the click handler to stay on the li (possibly because you have
other items in the li besides the checkbox).
Then this should do the trick nicely.
$('label').on('click', function(e) {
e.stopPropagation();
});
$('#toggle').on('click', function(e) {
e.stopPropagation();
$(this).closest('li').trigger('click');
});
Then you can write your own li click handler without worrying about events being triggered twice. Personally, I prefer to use a data-selected attribute that changes from false to true and vice versa each time the li is clicked instead of relying on the input's value:
$('ul.submenu li').on('click', function() {
let _li = $(this),
ticked = _li.attr('data-selected');
ticked = (ticked === 'false') ? true : false;
_li.attr('data-selected', ticked);
_li.find('#toggle').prop('checked', ticked);
});

Resources