I made a model-driven form in angular 2, and one of the input fields must show up only if a checkbox above is unchecked.I did this with *ngIf.
My question is how can I set that input required only if the checkbox is unchecked? In angular 1.x i could make this happen with the ng-required="condition" in the view.
Here is the html:
//the checkbox
<div class="checkbox col-sm-9">
<label>
<input type="checkbox" id="getCompanyAddress" style="cursor: pointer;" [formControl]="form.controls['address']" >Use the company address
</label>
</div>
// the option input:
<div *ngIf="form.value.address == false" class="form-group" [ngClass] = "{'has-error':!form.controls['address'].valid && form.controls['address'].touched}" >
<label for="add_gestion_adress" class="col-sm-3 control-label">Address
</label>
<div class="col-sm-9"><textarea rows="1" id="add_gestion_adress" class="form-control" name="add_gestion_adress" [formControl]="form.controls['address']" ></textarea>
</div>
</div>
//and the model code:
form: FormGroup;
constructor(fb:FormBuilder){
this.form = fb.group({
'name': [null,Validators.compose([Validators.required, Validators.minLength(1)])],
'type': ["en gros",Validators.compose([Validators.required, Validators.minLength(2)])],
'person':[null,Validators.compose([Validators.required, Validators.minLength(1)])],
'address':[false,Validators.compose([Validators.minLength(1)])],
'locality':[null, Validators.compose([Validators.required])],
'county':[null,Validators.compose([Validators.required])],
'country':[null,Validators.compose([Validators.required])]
})
}
<textarea [required]="your angular expression">
The above works in the latest version of Angular 4
One way to do it is to listen for value changes in the checkbox form control and add/remove validators in the other control accordingly.
Example:
this.form.get('checkbox-control').valueChanges.map(
value => {
if(value) {
this.form.get('other-control').setValidators(Validators.required);
}else {
this.form.get('other-control').clearValidators();
}
}
);
The FormBuilder takes a second argument which accepts a validator which is intended for cross-field validation:
this.form = fb.group({
'name': [null,Validators.compose([Validators.required, Validators.minLength(1)])],
'type': ["en gros",Validators.compose([Validators.required, Validators.minLength(2)])],
'person':[null,Validators.compose([Validators.required, Validators.minLength(1)])],
'address':[false,Validators.compose([Validators.minLength(1)])],
'locality':[null, Validators.compose([Validators.required])],
'county':[null,Validators.compose([Validators.required])],
'country':[null,Validators.compose([Validators.required])]
}
, { validator: this.crossFieldValidation });
You can define it to do whatever.
crossFieldValidation(ctrl: FormGroup): ValidationErrors|null {
let isRequired = ctrl.controls.myCheckbox.value === true;
let hasValue = ctrl.controls.myMaybeRequiredControlXX.value;
if (isRequired && !hasValue) return {XXrequired: true};
return null;
}
To check for the error for display/ngClass, use form.errors?.XXrequired or whatever key your crossFieldValidation() returned, instead of form.controls.XX.errors?.required.
Related
I have one checkbox and one textbox, now when I check the checkbox and write text in textbox at that time checkbox value and textbox value is inserted, but when I am uncheck the checkbox and write the text in textbox at that time textbox value is not inserted in database.
Here is my code
I used enum value for checkbox and textbox
Here is the enum code
public enum ChassisJobTypeEnum
{
LinerChange = 1,
ChainSetChange = 2
}
Here is the view design code
<div class="form-group row">
<label class="col-sm-3 col-form-label">Change Linear</label>
<div class="col-sm-3">
<input type="checkbox" class="form-group" id="ChassisJob#((int)ChassisJobTypeEnum.LinerChange)_Checked" placeholder="" />
</div>
<div class="col-sm-3">
<input type="text" class="form-group" id="ChassisJob.#((int)ChassisJobTypeEnum.LinerChange)_OtherJob" placeholder="" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">Change Chain Set</label>
<div class="col-sm-3">
<input type="checkbox" class="form-group" id="ChassisJob#((int)ChassisJobTypeEnum.ChainSetChange)_Checked" placeholder="" />
</div>
<div class="col-sm-3">
<input type="text" class="form-group" id="ChassisJob.#((int)ChassisJobTypeEnum.ChainSetChange)_OtherJob" placeholder="" />
</div>
</div>
<div class="form-group row">
<div class="col-sm-12">
<button type="submit" class="btn btn-primary" id="submit-form">Submit</button>
</div>
</div>
Now, when submit the form at that time ajax is calling to the controller
$('form').submit(function (event) {
event.preventDefault();
var chassisJobs = [];
chassisJob = {
ChassisJobsTypeId: #((int)ChassisJobTypeEnum.LinerChange),
Checked: $("#ChassisJob#((int)ChassisJobTypeEnum.LinerChange)_Checked").prop('checked'),
OtherJob: document.getElementById("ChassisJob.#((int)ChassisJobTypeEnum.LinerChange)_OtherJob").value,
};
chassisJobs.push(chassisJob);
chassisJob = {
ChassisJobsTypeId: #((int)ChassisJobTypeEnum.ChainSetChange),
Checked: $("#ChassisJob#((int)ChassisJobTypeEnum.ChainSetChange)_Checked").prop('checked'),
OtherJob: document.getElementById("ChassisJob.#((int)ChassisJobTypeEnum.ChainSetChange)_OtherJob").value,
};
chassisJobs.push(chassisJob);
var serviceJobData = {
'Id': document.getElementById("Id").value,
'ChassisJob': chassisJobs
};
$.ajax({
type: "POST",
url: '/ServiceJob/AddUpdate',
data: serviceJobData,
dataType: "json",
success: function (data) {
if (data.success == true) {
alert("Data has been update successfully");
//RefreshTable();
location.reload(true);
// set focus on edit form
document.getElementById("service-job-list").scrollIntoView();
//reste form
var frm = document.getElementsByName('service-job-form')[0];
frm.reset();
}
else {
alert("Unable to insert data")
}
error: function (xhr, ajaxOptions, thrownError) {
alert('Failed to add Detail.');
}
});
});
Here is the controller in which the addupdate method is calling at submit button.
[HttpPost]
public IActionResult AddUpdate(ServiceJobModel model)
{
ServiceJob serviceJob = new ServiceJob();
bool iSInsertData = true;
var chassisJobs = _Db.ChassisJob.Where(x => x.ServiceJobId == model.Id).ToList();
if (chassisJobs.Any())
{
_Db.ChassisJob.RemoveRange(chassisJobs);
_Db.SaveChanges();
}
return Json(new { success = true });
}
Now, this is code which I tried.
For more clear, let see task image.
When I check the checkbox and enter the value in textbox at that time insert data properly and at the fetch time it shows the checkbox and textbox value properly.
now, when I uncheck the checkbox and enter the value in textbox at that time data is not inserted and at the fetch time it does not show any thing.
If you any issue to understand the question then feel free to ask.
I've got a form with a text field and a few checkboxes. It works perfectly fine if I fill out the <input type="text"> field first, but if I mark the checkboxes first, the checkboxes aren't passed to my function on ng-submit().
HTML
<form ng-submit="createService(service)">
<input type="text" ng-model="service.name" required>
<div ng-repeat="provider in providers">
<md-checkbox id="{{ provider }}" ng-model="service.providers[provider.$id]">{{ provider.name }}</md-checkbox>
</div>
<button type="submit" class="h4 button button-big mb4" aria-label="Add Service">Add Service</button>
</form>
JS
$scope.createService = function(service) {
var checkedProviders = {};
var serviceProviders = service.providers;
for (var checked in serviceProviders) {
if (serviceProviders[checked]) {
checkedProviders[checked] = true;
}
}
services.$add({
name: service.name,
providers: checkedProviders
});
};
It's very weird and I can't work out why it is doing this. Any help on why this is happening is appreciated.
Thanks in advance.
When my model value is true then I want the radio buttons to be selected when loaded, but its happening the otherway around. All false models are getting selected. How do fix this.
http://plnkr.co/edit/DIYm4vBM3srdS61K6EPA?p=preview
angular.module('radioExample', [])
.controller('ExampleController', ['$scope',
function($scope) {
$scope.kind = [{
name: 'task',
selected: false
}, {
name: 'bug',
selected: false
}, {
name: 'other',
selected: true
}, {
name: 'rfe',
selected: false
}]
$scope.$watch('kind', function() {
console.log('changed', JSON.stringify($scope.kind, null, 2))
}, true)
}
]);
use ng-value here is the doc for angular radio
<input type="radio" name="" id="" value="" ng-model="k.selected" ng-value="true" />
then, if the ng-value is true and the model value is also true then check box will checked
here is the update Demo
<input type="checkbox" id="rempass" ng-model="rememberMe" ng-checked="rememberMeUserInfoCheck()" > $scope.rememberMeUserInfoCheck=function() { return true; }
this works for me
Add ng-checked ="true" to your radio input field
`<input type="radio" ng-model="modelName" name="radioName" value="value1" ng-checked="true">`
I fixed the plunker plunker
<form name="myForm" ng-controller="ExampleController">
<br />all 'false' radio buttons are selected when 'value' is used -------------
<br />
<div ng-repeat="k in kind">
<input type="radio" name="" id="" value="" ng-model="!k.selected" value="k.selected" />{{k.name}}
</div>
<br />all radio buttons are selected when 'ng-value' is used -------------
<br />
<div ng-repeat="k in kind">
<input type="radio" name="" id="" value="" ng-model="k.selected" ng-value="k.selected" />{{k.name}}
</div>
</form>
you had it right.... just needed to add a ! so the model will take the opposite of the scope value... since you are using them for both I guess its wont hurt your code
For those working with FormGroup and FormControl:
In the template:
Add formControlName = sameNameforAllRadioButtonsOfAChoice as an attribute to your radio button input tags.
Also add value = "true" and value = "false" (you can also do it with numbers and strings, but I will continue with boolean).
In the component:
Add the name, e.g. sameNameforAllRadioButtonsOfAChoice, to your FormGroup:
myForm = new FormGroup({sameNameforAllRadioButtonsOfAChoice: new FormControl('false')})
This sets the default value to false. In the FormControl, be careful to write it as a string!
BONUS - If you need Validation:
import { FormControl, FormGroup, Validators } from '#angular/forms';
myForm = new FormGroup({sameNameforAllRadioButtonsOfAChoice: new FormControl('false', [Validators.required])})
I want a button that is only enabled if at least one of a group of checkboxes is checked, similiar to the fiddle at http://jsfiddle.net/chriscoyier/BPhZe/76:
var checkboxes = $("input[type='checkbox']"),
submitButt = $("input[type='submit']");
checkboxes.click(function() {
submitButt.attr("disabled", !checkboxes.is(":checked"));
});
I want to implement this using AngularJs.
Add a function to your controller that checks if any of the check boxes are checked. If the radio button is checked its value will be true. Then, in the HTML use the ng-disabled directive on your button and set it equal to the result of your function. Example:
Controller:
$scope.isCheckboxChecked = function() {
return ($scope.checkbox1 || $scope.checkbox2 || $scope.checkbox3);
}
HTML:
<button type="button" ng-disabled="!isCheckboxChecked()">My Button</button>
It would be helpful if you posted the code you have already tried. My answer is assuming you already have functional check boxes using the ng-model directive and are just looking for how to disable the button when any of them are checked.
Update:
If you don't already have your checkboxes binding to your controller, here is an example. Note the use of ng-model to bind to a $scope.checkbox1 or $scope.checkbox2 variable in your scope.
<input type="checkbox" ng-model="checkbox1">Checkbox 1
<input type="checkbox" ng-model="checkbox2">Checkbox 2
Assuming that your form consists of a long list of check boxes, then alternatively you can create the list in the Controller's $scope and then iterate each check box items along with specific properties such as its label and its state(model) where it is checked or not. Next is to create a function that determines if any of the check box in the check box list has its state checked(isChecked).
Plunker DEMO
Controller
controller('Controller', function($scope) {
$scope.checkBoxes = [
{label: 'Option 1', isChecked: false},
{label: 'Option 2', isChecked: false},
{label: 'Option 3', isChecked: false},
{label: 'Option 4', isChecked: false},
{label: 'Option 5', isChecked: false}
];
$scope.isChecked = function() {
for(var e in $scope.checkBoxes) {
var checkBox = $scope.checkBoxes[e];
if(checkBox.isChecked)
return true;
}
return false;
};
});
At this point, you can iterate the check box list in your form and fill up properties(e.g. label) and its respective models(isChecked) in each check box.
HTML
<form ng-controller="Controller">
<div ng-repeat="checkBox in checkBoxes">
<input type="checkbox" ng-model="checkBox.isChecked" id="check-box-{{$index}}" />
<label ng-bind="checkBox.label" for="check-box-{{$index}}"></label>
</div>
<div>
<input type="submit" value="do thing" ng-disabled="!isChecked()" />
</div>
</form>
this could be a solution but it's not easy to understand what you are searching for
HTML
<h1>Button should be enabled if at least one checkbox is checked</h1>
<form>
<div>
<input type="checkbox" name="option-1" id="option-1" ng-click="check()"> <label for="option-1">Option 1</label>
</div>
<div>
<input type="checkbox" name="option-2" id="option-2" ng-click="check()"> <label for="option-2">Option 2</label>
</div>
<div>
<input type="checkbox" name="option-3" id="option-3"> <label for="option-3" ng-click="check()">Option 3</label>
</div>
<div>
<input type="checkbox" name="option-4" id="option-4"> <label for="option-4"ng-click="check()">Option 4</label>
</div>
<div>
<input type="checkbox" name="option-5" id="option-5"> <label for="option-5" ng-click="check()">Option 5</label>
</div>
<div>
<input type="button" ng-click="checkboxes" ng-disabled="enabled" value="Do thing" disabled>
</div>
</form>
JS
$scope.enabled=true
$scope.check=function(){
$scope.enabled=false
}
$scope.checkboxes=function() {
});
Finally it is done. I have done it using grep in jQuery.
$scope.userSelectionChanged = function () {
$scope.enableAddBtn = $.grep($scope.userlists, function (user) {
return user.IsSelected;
}).length >= 1;
};
HTML:
<ul>
<li><a><i class="icon-white icon-save"></i></a></li>
</ul>
<form>
<input type="text" value="{{ selectedUser.firstname }}" ng-model="selectedUser.firstname">
<input type="text" value="{{ selectedUser.lastname }}" ng-model="selectedUser.lastname">
</form>
I am dealing with user objects fetched from my REST API. So basically there is a list of users. On click the above form is revealed.
function UserController($scope, User){
$scope.users = User.query();
$scope.selectedUser = null;
$scope.select = function(user){
$scope.selectedUser = user;
}
}
I want to display the save link only when form values have changed. Any ideas how to do this with angular.js?
Give your form a name, such as:
<form name="dataForm">
<input type="text" name="firstname" ng-model="data.firstname" />
<input type="text" name="lastname" ng-model="data.lastname" />
</form>
The form will now be a named model in your scope and you can hide/show the save button based on whether the form is pristine:
<ul ng-hide="dataForm.$pristine">
<li><a><i class="icon-white icon-save"></i></a></li>
</ul>
This approach has the advantage of showing the save button if you change any of the form elements inside the form and the drawback of not checking the input values against their original values, just the fact that they have been edited.
Here is an example of showing your element only when both fields have data:
<div ng-controller="TestCtrl" ng-app>
<ul ng-show="enableSave(data)">
<li><a><i class="icon-white icon-save"></i></a></li>
</ul>
<form>
<input type="text" name="firstname" ng-model="data.firstname" />
<input type="text" name="lastname" ng-model="data.lastname" />
</form>
</div>
And here is your controller:
function TestCtrl($scope) {
$scope.data = {firstname: "", lastname: ""};
$scope.enableSave = function(data) {
return data.firstname.length > 1 && data.lastname.length > 1;
};
}
You can put any logic you want into enableSave. I've chosen to require that they both have at least two characters... you can do whatever you need.
Here is a jsFiddle that illustrates it: http://jsfiddle.net/nDCXY/1/
EDIT by OP: my solutions
$scope.enableSave = function(user) {
if(!angular.equals(user, oldUser)){
return true
}else{
return false;
}
};