So I have the following html:
<div class="workflow-row">
<input type="checkbox" id="new-workflow" [(ngModel)]="new_checkbox">
<label>New Workflow</label>
<input type="text" *ngIf="new_checkbox" placeholder="Enter Workflow Name">
</div>
<div class="workflow-row">
<input type="checkbox" id="edit-workflow" [(ngModel)]="edit_checkbox">
<label>Edit Workflow</label>
<select *ngIf="edit_checkbox"></select>
</div>
I want the checkboxes to act like radio buttons, ie: if one is checked, the other one becomes unchecked with angular 4. I tried doing
<input type="checkbox" id="edit-workflow" (click)="new_checkbox.checked = false"
[(ngModel)]="edit_checkbox">
but I get an error and it says that new_checkbox is undefined. The weird thing is that new_checkbox and edit_checkbox work inside the ngIf statements but not inside the (click)'s. What am I doing wrong?
I suggest you to try the following:
component.ts:
export class AppComponent {
edit_checkbox = false;
new_checkbox = true;
dropNewValue() {
this.new_checkbox = false;
}
dropEditValue() {
this.edit_checkbox = false;
}
}
Then in your template file, e.g. component.html, change your template slightly to:
<div class="workflow-row">
<input type="checkbox" id="new-workflow" [(ngModel)]="new_checkbox" (ngModelChange)="dropEditValue()">
<label>New Workflow</label>
<input type="text" *ngIf="new_checkbox" placeholder="Enter Workflow Name">
</div>
<div class="workflow-row">
<input type="checkbox" id="edit-workflow" [(ngModel)]="edit_checkbox" (ngModelChange)="dropNewValue()">
<label>Edit Workflow</label>
<select *ngIf="edit_checkbox"></select>
</div>
I've just tried this and it works. However I do recommend to switch to radio buttons approach, because you will get the same behavior out of the box.
Don't write Angular like you're writing regular javascript instead of
(click)="new_checkbox.checked = false"
do something like
// .html
(click)="uncheckNewCheckbox()"
// .js or .ts
uncheckNewCheckbox() {
this.new_checkbox.checked = false;
}
Related
I have a set of radio buttons. If a user selected the value "yes" I want to show an additional box on the form.
https://stackblitz.com/edit/angular-4bgahw?file=src/app/personal/personal.component.ts
HTML.component
<div formGroupName="radioButtonsGroup" class="form-group col-6 pl-0 pt-3">
<div class="form-check-inline" *ngFor="let item of personal.radioButtonsdata">
<label for="{{item.section}}" class="col-12 customradio"
><span>{{item.section}}</span>
<input [value]="item" id="{{item.section}}" type="radio" formControlName="selectedButton"/>
<span class="checkmark"></span>
</label>
</div>
<!-- <div class="col-md-8" *ngIf="selectedButton.control.item === 'yes'"> --> //my attempt to target above input value
<div class="col-md-8" >
<input type="text" formControlName="title" class="form-control" placeholder="Title">
</div>
</div>
Can anybody get this to work and show me what I am doing wrong here please?
You need to access the value of the form control:
*ngIf="form.get('radioButtonsGroup.selectedButton').value.section === 'yes'">
STACKBLITZ
Everything you write in the template is resolved against the corresponding class (or against template variables), so you have to refer to the JavaScript control like this:
*ngIf="form.controls['selectedButton'].value === 'yes'"
Call a function to set flag based on value of the radio button, (ngModelChange)="onRadiochange($event)"
Try like this:
Working Demo
.html
<input [value]="item" (ngModelChange)="onRadiochange($event)" id="{{item.section}}" type="radio" formControlName="selectedButton" />
<div class="col-md-8" *ngIf="showTitle">
<input type="text" formControlName="title" class="form-control" placeholder="Title">
</div>
.ts
onRadiochange(e) {
if(e.section == 'yes'){
this.showTitle = true
} else {
this.showTitle = false
}
}
It can also be done in one line like this:
<input [value]="item" (ngModelChange)="$event.section == 'yes' ? showTitle=true:showTitle=false" id="{{item.section}}" type="radio" formControlName="selectedButton" />
Whenever yes checkbox is selected, you have to display the title textbox.
In that case, change your code like this.
In personal.component.ts, add this variable.
yesSelected: boolean = true;
Also in ngOnInit(),
this.form.valueChanges.subscribe(val=>{
if(val.radioButtonsGroup.selectedButton.section === "yes")
this.yesSelected = true;
else
this.yesSelected = false;
});
In personal.component.html, rewrite your if condition like this.
<div class="col-md-8" *ngIf="yesSelected">
<input type="text" formControlName="title" placeholder="Title">
</div>
These changes will show the title textbox only when the yes check box is selected.
I need to toggle class .has-data on label if input has some data
<label>
<input type="text">
</label>
Can it be done just using some markup without writing javascript?
No, you'll have to write some JavaScript, but the JavaScript is pretty minimal. Change the HTML to this:
<label class="{ has-data: entry }">
<input type="text" onkeyup="{updateEntry}">
</label>
And add this section to the component's script:
<script>
this.entry = '';
updateEntry(e) {
this.entry = e.target.value;
}
</script>
I have the following form :
<form class="form-inline" role="form">
<div class="col-xs-3">
<div class="pic-container">
<div class="checkbox">
<label>
<input type="checkbox" name="discounting" onchange='handleChange(this);' id='check11' > Show only price-discounted products
</label>
</div>
</div>
</div>
<div class="col-xs-3">
<div class="pic-container">
<div class="checkbox" id='check21'>
<label>
<input type="checkbox" name="discounting" onchange='' id='check21'> Show only price-discounted products
</label>
</div>
</div>
</div>
</form>
I'd like to be able to check the second checkbox automatically with JavaScript once I check the first one. I tried using the following script :
<script>
function handleChange(cb) {
if(cb.checked == true) {
alert('Message 1');
document.getElementById("check21").checked = true;
} else {
alert('Message 2');
var x = document.getElementById("check21").disabled= false;
}
}
</script>
But it doesn't work since I think with bootstrap is a question of classes.
The problem as Didier pointed out is that you have two elements with the same ID:
<div class="checkbox" id='check21'>
and
<input type="checkbox" name="discounting" onchange='' id='check21'>
The call to document.getElementById('check21') will probably (because the behavior is undefined) return the first one, which in this case is the <div> element, not the checkbox.
You must not use the same ID on two HTML elements, so you need to change the ID on one or the other of them.
http://jsfiddle.net/uywaxds5/2/
I included boostrap as an external reference.
<div class="checkbox" id='check22'>
<label>
<input type="checkbox" name="discounting" onchange='' id='check21'> Show only price-discounted products
</label>
</div>
Fixing the duplicate id seems to work.
If it does not works, the issue might be in another part of your code.
Use a different name for the second radio button
<input type="checkbox" name="discounting21">
There can only be one selected radio button belonging to the same group(ie. name).
Okay so here is my setup i have the following array:
answers = [answer1, answer2]
with these i do the following:
<form>
<div class="col-xs-12" ng-repeat="answer in component.question.answers">
<div class="col-xs-1" style="width: 1%">
<div class="radio">
<label class="i-checks">
<input type="radio" name="a" ng-model="answer.is_correct">
<i></i>
</label>
</div>
</div>
<div class="col-xs-11">
<input type="text" ng-model="answer.answer" class="form-control" placeholder="Svar">
</div>
</div>
</form>
Now the input[radio] are inside the same form as they should. My goal is that when i set one as selected both of the answer objects should be updated so that only one of the object has the value is_correct = true
However what happens right now is that if i click the first and then second both values have is_correct = true
So what can i do?
Radio buttons are used to choose between different values for a single field or, in Angular's case, a single model. The logical solution would be to select the correct answer:
<input type="radio" ng-model="component.question.correctAnswer" ng-value="answer">
If you really need to set a flag you can easily achieve that with a watcher:
$scope.$watch('component.question.correctAnswer', function(correctAnswer) {
component.question.answers.forEach(function(answer) {
answer.is_correct = answer === correctAnswer ? true : false;
});
});
I'm trying to check whether a check box is checked, and if it is checked, then I want to add the "required" attribute to an adjacent text field. I've tried it two different ways with no success. Here are the form elements and my two JQuery attempts.
neither of those will actually trigger the event. My browser either does nothing at all or triggers an "Empty string passed to getElementById()." event
Form elements:
<div class="col-sm-5">
<label id="checkboxNumber-label" class="toplabel" for="checkboxNumber">Checkbox</label>
<g:textField name="checkboxNumber" value="${...checkboxNumber}" class="form-control" required="" aria-labelledby="checkboxNumber-label"/>
<label class="checkbox-inline">
<g:checkBox name="checkboxYesNo" id="checkboxYesNo" value="${...checkboxYesNo}" onclick="chkboxYesChecked()"/>
</label>
</div>
<div class="col-sm-5">
<label id="someTextField-label" class="toplabel" for="someTextField">Some Text Field Here</label>
<g:textField name="someTextField" id="someTextField" value="${...someTextField}" class="form-control" aria-labelledby="someTextField-label"/>
</div>
JQuery:
function chkboxYesChecked(){
if($('#checkboxYesNo').prop('checked')){
$('#someTextField').prop('required',true);
$('#someTextField').append('<span class="required-indicator">*</span>');
}else{
$('#someTextField').removeAttr('required');
}
}
$(document).ready(function() {
$('#checkboxYesNo').click(function() {
if($(this).is(":checked"))
{
$('#someTextField').prop('required',true);
$('#someTextField').append('<span class="required-indicator">*</span>');
} else {
$('#someTextField').removeAttr('required');
}
});
});
With your markup this becomes more convoluted than it needs to be.
$(document).on("click", ".checkbox-inline :checkbox", function () {
var $nextTextbox = $(this).closest("div").next("div").find(":text").first();
if (this.checked) {
$nextTextbox.prop("required", true).after('<span class="required-indicator">*</span>');
} else {
$nextTextbox.prop("required", false).next('.required-indicator').remove();
}
});
Notes
This approach uses event delegation.
There are no IDs involved, because I suppose you need the same thing more than once on your page. Tying it to a specific element ID is counter-productive.
This approach relies on the specific document structure from your sample Grails template. If you want something more flexible and easier-to-read, change your HTML.
This applies to all checkboxes that have a text field in the immediately following <div>. Use CSS classes on your elements to filter it/make it apply to specific ones only.
If there is no immediately following <div> with a text box, the function does nothing.
$(this).is(":checked") is superfluous. You don't need jQuery to find out if the current DOM element is checked. this.checked is a lot simpler and has the same effect.
Don't use inline event handlers (onclick="..."). Ever.
See it in action:
$(document).on("click", ".checkbox-inline :checkbox", function () {
var $nextTextbox = $(this).closest("div").next("div").find(":text").first();
if (this.checked) {
$nextTextbox.prop("required", true).after('<span class="required-indicator">*</span>');
} else {
$nextTextbox.prop("required", false).next('.required-indicator').remove();
}
});
input[required] {
background-color: #FFD1D1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-sm-5">
<label id="checkboxNumber-label" class="toplabel" for="checkboxNumber">Checkbox</label>
<input type="text" name="checkboxNumber" value="${...checkboxNumber}" class="form-control" required="" aria-labelledby="checkboxNumber-label" />
<label class="checkbox-inline">
<input type="checkbox" name="checkboxYesNo" id="checkboxYesNo" value="${...checkboxYesNo}" />
</label>
</div>
<div class="col-sm-5">
<label id="someTextField-label" class="toplabel" for="someTextField">Some Text Field Here</label>
<input type="text" name="someTextField" id="someTextField" value="${...someTextField}" class="form-control" aria-labelledby="someTextField-label" />
</div>