Angular 2 - Handle click on disabled input - html

This is what I have right now. Trying to call the checkToEnable function.
<input type="text" ([ngModel])="city.arr.date" [id]="city.id+'_arr_date'" [name]="city.id+'_arr_date'" [attr.disabled]="selectedTripType=='OT' ? true : null" class="input-icon-date input-default-last form-control" (click)="checkToEnable()" placeholder="Return Date"/>

Disabled elements don't fire mouse events. Most browsers will
propagate an event originating from the disabled element up the DOM
tree, so event handlers could be placed on container elements.
But you can achieve it by this way :
Component Side:
disableTextbox = false;
toggleDisable() {
this.disableTextbox = !this.disableTextbox;
}
Template side :
<div (click)='toggleDisable()'>
<input [disabled]='disableTextbox' >
</div>
WORKING DEMO

Related

Space keypress on an HTML Label interpreted as checkbox click

When I add 'click' event handler on an HTML checkbox with a label, then space keypress on the label causes the checkbox's click event handler to be executed. I would like to prevent that. (The checkbox itself is hidden / not visible - this is done in some version of Bootstrap framework used in my code).
HTML:
<body>
<label for="checkbox" id="label">Click on me, I am Label for <strong>hidden</strong> Checkbox</label>
<!-- checkbox is not visible -->
<input type="checkbox" id="checkbox" style="opacity: 0" />
<!-- to be filled by JavaScript code -->
<div id="checkboxValue"></div>
</body>
JavaScript code:
import { fromEvent } from 'rxjs';
const checkbox: HTMLInputElement = document.querySelector('#checkbox');
const checkboxValue: HTMLDivElement = document.querySelector('#checkboxValue');
function updateCheckbox() {
checkboxValue.innerHTML = `Checkbox ${
checkbox.checked ? '✔️ (checked)' : '❌ (unchecked)'
}`;
}
// event handler for the checkbox being executed also for Space keypress:
fromEvent(checkbox, 'click').subscribe((event) => {
console.log('checkbox CLICK -------')
updateCheckbox();
});
updateCheckbox();
Open the Stackblitz console, click the Click on me, I am Label for hidden Checkbox.
Then press the space key and see the click handler being executed.
Demo on Stackblitz.
If a label has keyboard focus, pressing the Space key also raises the Click event.
If you want to remove focus, you can add a blur event (on the label) to remove focus so spacebar won't function to click the button :
e.target.blur();

ng-multiselect-dropdown - programmatically clear selected items not visually working

I am using ng-multiselect-dropdown when clicking the deselect option within the object itself the dropdown clears the selected items (visually and variable
When programmatically clearing the selectedItems the variable array itself is cleared but the selected items within the visual portion are still selected. If you were to then click within the object the values would no longer be available as a selection but visually the object does not clear.
I've tried a few options to clear I'll show here below. I've also tried to put it into a form and then manually clearing the control.In any scenario I've tried when not deselectingAll from the dropdown itself the visual portion remains cached and the selectedItems is empty.
Form:
<form [formGroup]="multiselect" (ngSubmit)="onSubmit()">
<div>
<ng-multiselect-dropdown [placeholder]=""
[settings]="settings"
[data]="propertiesCharUnique"
(onSelect)="onItemSelect($event)"
(onSelectAll)="onSelectAll($event)"
(onDeSelect)="onDeSelect($event)"
(onDeSelectAll)="onDeSelectAll($event)"
formControlName="multi"
[(ngModel)]="selectedItems"
>
</ng-multiselect-dropdown>
<input type="submit" value="Load Targets" />
</div>
#ViewChild('multiselect') multiSelect: any;
multiselect = this.formBuilder.group({
});
public reset(){
this.multiselect.get("multi")?.setValue([]);
this.multiselect.get("multi")?.reset()
this.selectedItems = [];
}
I removed the dropdown from the form and now ngModel binds properly.
<div>
<ng-multiselect-dropdown
[placeholder]="'Click here to select'"
[settings]="settings"
[data]="propertiesCharUnique"
[(ngModel)]="selectedItems"
(onSelect)="onItemSelect($event)"
(onSelectAll)="onSelectAll($event)"
(onDeSelect)="onDeSelect($event)"
(onDeSelectAll)="onDeSelectAll($event)" >
</ng-multiselect-dropdown>
<input type="submit" (ngSubmit)="onSubmit()" value="Load Targets" />
</div>

Prevent expand on click on prime ng accordion

I have an primeng accordion and the accordion header has a checkbox control . Whenever i check/uncheck checkbox , the accordion tab is getting open/closed automatically
Is there any way to prevent expand/collapse on click on checkbox ? It should expand/collapse on header other than check/uncheck check box ?
This is happening due to Event Bubbling. For this need to stop eventPropagation by calling stopPropagation() of MouseEvent.
Accordion html code sample
<p-accordion>
<p-accordionTab header="Godfather I" [selected]="true">
<p-header>
<span>Godfather I
<input type="checkbox" (click)="onClick($event)">
</span>
</p-header>
Some Text
</p-accordionTab>
</p-accordion>
Corresponding component ts code.
onClick($event: MouseEvent){
$event.stopPropagation();
}
For Reference added stackblitz code sample.
This is how I solved this issue. This is happening because of Event Bubbling. So when you click on child element. Event propagate to its parent and so on. So Just use stop propagation on event. It will prevent the click event on your accordion. Below code for your reference.
Accordian with Check box code I used (onChange) method.
<p-accordionTab>
<p-header>
<div class="ui-g" style="width:250px;margin-bottom:10px">
<div class="ui-g-12"><p-checkbox name="group1" #ck value="New York" label="New York" [(ngModel)]="selectedCities" (onChange)="checkChange($event)" inputId="ny"></p-checkbox></div>
</div>
</p-header>
</p-accordionTab>
component.ts
selectedCities: string[] = [];
//Simply you have to to stop propogation here.
checkChange(e:any){
console.log(e); // true or false.
event.stopPropagation(); // component will have direct access to event here.
}

How to reset check status in html

I have popup in HTML
<div id="term_flags" class="term_flags">
<div class="modal-users-content flagsContent">
<div class="modal-users-header">
<span class="close" ng-click="closeFlagsPopup()">×</span>
<a> Check terminal flags </a>
</div>
<div class="modal-flags-body">
<div class="checkBoxes">
<div class="checkerDiv">
<input type="checkbox" ng-model='reservedFlag' ng-click='changeReservedStatus(reservedFlag)' value="flag" ng-checked="reservedFlag"> Reserved
</div>
<div class="checkerDiv">
<input type="checkbox" ng-model='seasonFlag' ng-click='changeSeasonStatus(seasonFlag)' value="flag" ng-checked="seasonFlag"> Season
</div>
<div class="checkerDiv">
<input type="checkbox" ng-model='networkFlag' ng-click='changeNetworkStatus(networkFlag)' value="flag" ng-checked="networkFlag"> Network
</div>
</div>
<div class="saveFlags">
<button class="button button6" name="changeFlags" value="Change Flags" type="submit" ng-click="saveFlags(item.terminalId)"> Save <p> </button>
</div>
</div>
<div class="modal-footer"></div>
</div>
</div>
this div's display is none in the beginning. but some ng-click is called from outside of this div and display is changed from none to block and initializes checkbox statuses in this angular function
$scope.changeFlagStatus = function(item)
{
$scope.reservedFlag=(item.reservedFlag=='T')?true:false;
$scope.networkFlag=(item.networkFlag=='T')?true:false;
$scope.seasonFlag=(item.seasonFlag=='T')?true:false;
document.getElementById('term_flags').style.display = "block";
}
everything is okay , but when i click on reservedFlag changeReservedStatus(reservedFlag) method was called and change reservedFlag's checked status
$scope.changeReservedStatus = function(item) {
$scope.reservedForSave=item;
}
I saved this status in other variable and close my popup windows document.getElementById('term_flags').style.display=none
when i open this popup window again my function changeFlagStatus(item) is called again and initializes my variables for checkbox correctly but my checkbox are incorrect checked .
In example when i opened my popup window first time my variables after initialize were
$scope.reservedFlag=true;
$scope.networkFlag=false;
$scope.seasonFlag=true;
and my checkbox statuses were
reservedFlag = checked
networkFlag = unchecked
seasonFlag = checked
then i clicked on reservedFlag and changed his status from checked to unchecked and close my popup windows.
then i opened it second time and changeFlagStatus(item) method is called again to initialize my variables again for checkbox statuses
and i want to get
reservedFlag = checked
networkFlag = unchecked
seasonFlag = checked
again, but result is
reservedFlag = unchecked
networkFlag = unchecked
seasonFlag = checked
How can i get it ?
Angularjs won't work pretty good with $scope's properties for primitive variables when used again and again.
I would recommend you to declare an object to scope and set these flags as properties to this object.
$scope.flags = {};
$scope.changeFlagStatus = function(item)
{
$scope.flags.reservedFlag=(item.reservedFlag=='T')?true:false;
$scope.flags.networkFlag=(item.networkFlag=='T')?true:false;
$scope.flags.seasonFlag=(item.seasonFlag=='T')?true:false;
document.getElementById('term_flags').style.display = "block";
}
and the html part as
<input type="checkbox" ng-model='flags.reservedFlag' ng-change='changeReservedStatus()' value="flag" ng-checked="flags.reservedFlag"> Reserved
Instead of ng-click, I would recommend to use ng-change because that is the event to be used with checkbox. If you use ng-change, the injection of the model as a parameter can be avoided which helps in utilizing angularjs's feature of 2-way binding.
You can add ng-true-value and ng-false-value to the checkbox with true and false to make it more easier to handle instead of ng-value.
I would write the html part like this.
<input type="checkbox" ng-model='flags.reservedFlag' ng-change='changeReservedStatus()' ng-true-value="true" ng-false-value="false"> Reserved
Hope this will fix the issue.

Tri-state Check box in HTML?

There is no way to have a tri-state check button (yes, no, null) in HTML, right?
Are there any simple tricks or work-arounds without having to render the whole thing by oneself?
Edit — Thanks to Janus Troelsen's comment, I found a better solution:
HTML5 defines a property for checkboxes called indeterminate
See w3c reference guide. To make checkbox appear visually indeterminate set it to true:
element.indeterminate = true;
Here is Janus Troelsen's fiddle. Note, however, that:
The indeterminate state cannot be set in the HTML markup, it can only be done via Javascript (see this JSfiddle test and this detailed article in CSS tricks)
This state doesn't change the value of the checkbox, it is only a visual cue that masks the input's real state.
Browser test: Worked for me in Chrome 22, Firefox 15, Opera 12 and back to IE7. Regarding mobile browsers, Android 2.0 browser and Safari mobile on iOS 3.1 don't have support for it.
Previous answer
Another alternative would be to play with the checkbox transparency
for the "some selected" state (as Gmail does used to
do in previous versions). It will require some javascript and a CSS
class. Here I put a particular example that handles a list with
checkable items and a checkbox that allows to select all/none of them.
This checkbox shows a "some selected" state when some of the list
items are selected.
Given a checkbox with an ID #select_all and several checkboxes with
a class .select_one,
The CSS class that fades the "select all" checkbox would be the
following:
.some_selected {
opacity: 0.5;
filter: alpha(opacity=50);
}
And the JS code that handles the tri-state of the select all checkbox
is the following:
$('#select_all').change (function ()
{
//Check/uncheck all the list's checkboxes
$('.select_one').attr('checked', $(this).is(':checked'));
//Remove the faded state
$(this).removeClass('some_selected');
});
$('.select_one').change (function ()
{
if ($('.select_one:checked').length == 0)
$('#select_all').removeClass('some_selected').attr('checked', false);
else if ($('.select_one:not(:checked)').length == 0)
$('#select_all').removeClass('some_selected').attr('checked', true);
else
$('#select_all').addClass('some_selected').attr('checked', true);
});
You can try it here: http://jsfiddle.net/98BMK/
You could use HTML's indeterminate IDL attribute on input elements.
My proposal would be using
three appropriate unicode characters for the three states e.g. ❓,✅,❌
a plain text input field (size=1)
no border
read only
display no cursor
onclick handler to toggle thru the three states
See examples at:
http://jsfiddle.net/wf_bitplan_com/941std72/8/
/**
* loops thru the given 3 values for the given control
*/
function tristate(control, value1, value2, value3) {
switch (control.value.charAt(0)) {
case value1:
control.value = value2;
break;
case value2:
control.value = value3;
break;
case value3:
control.value = value1;
break;
default:
// display the current value if it's unexpected
alert(control.value);
}
}
function tristate_Marks(control) {
tristate(control,'\u2753', '\u2705', '\u274C');
}
function tristate_Circles(control) {
tristate(control,'\u25EF', '\u25CE', '\u25C9');
}
function tristate_Ballot(control) {
tristate(control,'\u2610', '\u2611', '\u2612');
}
function tristate_Check(control) {
tristate(control,'\u25A1', '\u2754', '\u2714');
}
<input type='text'
style='border: none;'
onfocus='this.blur()'
readonly='true'
size='1'
value='❓' onclick='tristate_Marks(this)' />
<input style="border: none;"
id="tristate"
type="text"
readonly="true"
size="1"
value="❓"
onclick="switch(this.form.tristate.value.charAt(0)) {
case '&#x2753': this.form.tristate.value='✅'; break;
case '&#x2705': this.form.tristate.value='❌'; break;
case '&#x274C': this.form.tristate.value='❓'; break;
};" />
You can use radio groups to achieve that functionality:
<input type="radio" name="choice" value="yes" />Yes
<input type="radio" name="choice" value="No" />No
<input type="radio" name="choice" value="null" />null
Here is a runnable example using the mentioned indeterminate attribute:
const indeterminates = document.getElementsByClassName('indeterminate');
indeterminates['0'].indeterminate = true;
<form>
<div>
<input type="checkbox" checked="checked" />True
</div>
<div>
<input type="checkbox" />False
</div>
<div>
<input type="checkbox" class="indeterminate" />Indeterminate
</div>
</form>
Just run the code snippet to see how it looks like.
You can use an indeterminate state: http://css-tricks.com/indeterminate-checkboxes/. It's supported by the browsers out of the box and don't require any external js libraries.
I think that the most semantic way is using readonly attribute that checkbox inputs can have. No css, no images, etc; a built-in HTML property!
See Fiddle:
http://jsfiddle.net/chriscoyier/mGg85/2/
As described here in last trick:
http://css-tricks.com/indeterminate-checkboxes/
Like #Franz answer you can also do it with a select. For example:
<select>
<option></option>
<option value="Yes">Yes</option>
<option value="No">No</option>
</select>
With this you can also give a concrete value that will be send with the form, I think that with javascript indeterminate version of checkbox, it will send the underline value of the checkbox.
At least, you can use it as a callback when javascript is disabled. For example, give it an id and in the load event change it to the javascript version of the checkbox with indeterminate status.
Besides all cited above, there are jQuery plugins that may help too:
for individual checkboxes:
jQuery-Tristate-Checkbox-plugin: http://vanderlee.github.io/tristate/
for tree-like behavior checkboxes:
jQuery Tristate: http://jlbruno.github.io/jQuery-Tristate-Checkbox-plugin/
EDIT
Both libraries uses the 'indeterminate' checkbox attribute, since this attribute in Html5 is just for styling (https://www.w3.org/TR/2011/WD-html5-20110113/number-state.html#checkbox-state), the null value is never sent to the server (checkboxes can only have two values).
To be able to submit this value to the server, I've create hidden counterpart fields which are populated on form submission using some javascript. On the server side, you'd need to check those counterpart fields instead of original checkboxes, of course.
I've used the first library (standalone checkboxes) where it's important to:
Initialize the checked, unchecked, indeterminate values
use .val() function to get the actual value
Cannot make work .state (probably my mistake)
Hope that helps.
Refering to #BoltClock answer, here is my solution for a more complex recursive method:
http://jsfiddle.net/gx7so2tq/2/
It might not be the most pretty solution but it works fine for me and is quite flexible.
I use two data objects defining the container:
data-select-all="chapter1"
and the elements itself:
data-select-some="chapter1"
Both having the same value. The combination of both data-objects within one checkbox allows sublevels, which are scanned recursively. Therefore two "helper" functions are needed to prevent the change-trigger.
Here other Example with simple jQuery and property data-checked:
$("#checkbox")
.click(function(e) {
var el = $(this);
switch (el.data('checked')) {
// unchecked, going indeterminate
case 0:
el.data('checked', 1);
el.prop('indeterminate', true);
break;
// indeterminate, going checked
case 1:
el.data('checked', 2);
el.prop('indeterminate', false);
el.prop('checked', true);
break;
// checked, going unchecked
default:
el.data('checked', 0);
el.prop('indeterminate', false);
el.prop('checked', false);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label><input type="checkbox" name="checkbox" value="" checked id="checkbox"> Tri-State Checkbox </label>
As I needed something like this -without any plug-in- for script-generated checkboxes in a table... I ended up with this solution:
<!DOCTYPE html>
<html>
<body>
Toto <input type="checkbox" id="myCheck1" onclick="updateChkBx(this)" /><br />
Tutu <input type="checkbox" id="myCheck2" onclick="updateChkBx(this)" /><br />
Tata <input type="checkbox" id="myCheck3" onclick="updateChkBx(this)" /><br />
Tete <input type="checkbox" id="myCheck4" onclick="updateChkBx(this)" /><br />
<script>
var chkBoxState = [];
function updateChkBx(src) {
var idx = Number(src.id.substring(7)); // 7 to bypass the "myCheck" part in each checkbox id
if(typeof chkBoxState[idx] == "undefined") chkBoxState[idx] = false; // make sure we can use stored state at first call
// the problem comes from a click on a checkbox both toggles checked attribute and turns inderminate attribute to false
if(chkBoxState[idx]) {
src.indeterminate = false;
src.checked = false;
chkBoxState[idx] = false;
}
else if (!src.checked) { // passing from checked to unchecked
src.indeterminate = true;
src.checked = true; // force considering we are in a checked state
chkBoxState[idx] = true;
}
}
// to know box state, just test indeterminate, and if not indeterminate, test checked
</script>
</body>
</html>
A short snippet using an auxiliary variable and indeterminate:
cb1.state = 1
function toggle_tristate(cb) {
cb.state = ++cb.state % 3 // cycle through 0,1,2
if (cb.state == 0) {
cb.indeterminate = true;
cb.checked = true; // after 'indeterminate' the state 'false' follows
}
}
<input id="cb1" type="checkbox" onclick="toggle_tristate(this)">
Only state==0 is captured. The rest is handle automatically.
http://jsfiddle.net/6vyek2c5
You'll need to use javascript/css to fake it.
Try here for an example: http://www.dynamicdrive.com/forums/archive/index.php/t-26322.html
It's possible to have HTML form elements disabled -- wouldn't that do? Your users would see it in one of three states, i.e. checked, unchecked, and disabled, which would be greyed out and not clickable. To me, that seems similar to "null" or "not applicable" or whatever you're looking for in that third state.
There's a simple JavaScript tri-state input field implementation at
https://github.com/supernifty/tristate-checkbox
The jQuery plugin "jstree" with the checkbox plugin can do this.
http://www.jstree.com/documentation/checkbox
-Matt
Building on the answers above using the indeterminate state, I've come up with a little bit that handles individual checkboxes and makes them tri-state.
MVC razor uses 2 inputs per checkbox anyway (the checkbox and a hidden with the same name to always force a value in the submit). MVC uses things like "true" as the checkbox value and "false" as the hidden of the same name; makes it amenable to boolean use in API calls. This snippet uses a third hidden state to persist the last request values across submits.
Checkboxes initialized with the below will start indeterminate. Checking once turns on the checkbox. Checking twice turns off the checkbox (returning the hidden value of the same name). Checking a third time returns it to indeterminate (and clears out the hidden so a submit will produce a blank).
The page also populates another hidden (e.g., triBox2Orig) with whatever value was on the query string to start, so the 3 states can be initialized and persisted between submits.
$(document).ready(function () {
var initCheckbox = function (chkBox)
{
var hidden = $('[name="' + $(chkBox).prop("name") + '"][type="hidden"]');
var hiddenOrig = $('[name="' + $(chkBox).prop("name") + 'Orig"][type="hidden"]').prop("value");
hidden.prop("origValue", hidden.prop("value"));
if (!chkBox.prop("checked") && !hiddenOrig) chkBox.prop("indeterminate", true);
if (chkBox.prop("indeterminate")) hidden.prop("value", null);
chkBox.change(checkBoxToggleFun);
}
var checkBoxToggleFun = function ()
{
var isChecked = $(this).prop('checked');
var hidden = $('[name="' + $(this).prop("name") + '"][type="hidden"]');
var thirdState = isChecked && hidden.prop("value") === hidden.prop("origValue");
if (thirdState) { // on 3rd click of a checkbox, set it back to indeterminate
$(this).prop("indeterminate", true);
$(this).prop('checked', false);
}
hidden.prop("value", thirdState ? null : hidden.prop("origValue"));
};
var chkBox = $('#triBox1');
initCheckbox(chkBox);
chkBox = $('#triBox2');
initCheckbox(chkBox);
});