AngularJS client application.
I have a form with two text inputs and a drop down listbox. Only one of the two text inputs is enabled, the selected item in the listbox determines which input is enabled.
The two text inputs are associated with fields in the model. However, when a text input is disabled, I would like the value to be cleared, not visible in a disabled state. When the input is enabled again, the model value should be displayed.
What is the best way to achieve this with AngularJS?
Angular Expression can be used with ngDisabled directive.
Use ternary operator to check if selected value is equal to name of the input field and based on that set ngDisabled.
If the expression is truthy, then the disabled attribute will be set on the element.
Something like this in your html template.
ngDisabled = "($scope.input_model_variable_name != $scope.select_model_variable_name)?true:false"
One way to go about it would be
Call a function on ng-change on select.
-- copy all the values to restore later
-- blank all the text fields except for the field you want to edit
Have a function for ng-disable
-- disable the not selected text box
-- enable the rest
var app = angular.module('testApp', []);
app.controller('MainCtrl', function ($scope) {
var modelCopy = {
inputTextField1: "",
inputTextField2: ""
};
$scope.data = {
inputTextField1: "",
inputTextField2: "",
selectedInputField: ""
};
$scope.inputFieldChanged = function () {
angular.forEach(modelCopy, function (value, key) {
modelCopy[key] = $scope.data[key];
if (this.selectedInputField === key) {
this[key] = value;
} else {
this[key] = "";
}
}, $scope.data);
};
$scope.toggleDisability = function (fieldToEnable) {
if ($scope.data.selectedInputField === fieldToEnable) {
return false;
} else {
return true;
}
};
});
HTML
<div ng-controller="MainCtrl">
<div class="container">
<form novalidate="novalidate" class="form-horizontal">
<div class="form-group">
<label for="selectInputFieldToEdit" class="control-label col-sm-2">Select Input Field to Edit</label>
<div class="col-sm-6">
<select class="form-control" ng-change="inputFieldChanged()" id="selectInputFieldToEdit" ng-model="data.selectedInputField">
<option value="inputTextField1">Field 1</option>
<option value="inputTextField2">Field 2</option>
</select>
</div>
</div>
<div class="form-group">
<label for="inputTextField1" class="control-label col-sm-2">Input Text Field 1</label>
<div class="col-sm-6">
<input id="inputTextField1" type="text" ng-model="data.inputTextField1" name="inputTextField1" class="form-control" ng-disabled="toggleDisability('inputTextField1')" />
</div>
</div>
<div class="form-group">
<label for="inputTextField2" class="control-label col-sm-2">Input Text Field 2</label>
<div class="col-sm-6">
<input id="inputTextField2" type="text" ng-model="data.inputTextField2" name="inputTextField2" class="form-control" ng-disabled="toggleDisability('inputTextField2')" />
</div>
</div>
</form>
</div>
</div>
Here is a jsFiddle https://jsfiddle.net/hheymu/jpydjuhp/
Related
I have a javascript function that takes a value from a select and append its to the end of a textarea field (mask) whenever a new selection is made from the select
function addToEditMask(select, mask)
{
var selectedValue = document.getElementById(select).value;
document.getElementById(mask).append(" + "+selectedValue);
}
This function is used by two different elements on the same page as follows:
<div class="form-group">
<label for="edit_filename_mask_mask" id="edit_filename_mask_masklabel">
Mask
</label>
<textarea type="text" id="edit_filename_mask_mask" name="edit_filename_mask_mask"
aria-describedby="edit_filename_mask_masklabel" class="form-control" rows="10" cols="80"></textarea>
</div>
<div class="form-group">
<label for="editMaskVarList" id="editMaskVarListlabel">
Mask Fields
</label>
<select class="mb-2 form-control custom-select" id="editMaskVarList" onchange="addToEditMask('editMaskVarList', 'edit_filename_mask_mask');">
<option>
acoustic (Acoustic)
</option>
.....
and
<div class="form-group">
<label for="add_filename_mask_mask" id="add_filename_mask_masklabel">
Mask
</label>
<textarea type="text" id="add_filename_mask_mask" name="add_filename_mask_mask"
aria-describedby="add_filename_mask_masklabel" class="form-control" rows="10" cols="80"></textarea>
</div>
<div class="form-group">
<label for="addMaskVarList" id="addMaskVarListlabel">
Mask Fields
</label>
<select class="mb-2 form-control custom-select" id="addMaskVarList" onchange="addToEditMask('addMaskVarList', 'add_filename_mask_mask');">
<option>
acoustic (Acoustic)
</option>
......
In each case the select and the mask are both within a Bootstrap modal dialog. But it only works for the second case (add_filename_mask_mask) not the first case (edit_filename_mask_mask)
I added some debugging to ensure
function addToEditMask(select, mask)
{
var selectedValue = document.getElementById(select).value;
document.getElementById(mask).append(" + "+selectedValue);
alert('Adding to mask:'+mask+':'+scriptvar+':'+document.getElementById(mask).value);
}
that the function was actually being called in both cases and all the variables a renamed correctly. Yet although there are no webconsole errors and the append() method doesnt report any error the value of mask doesnt change for edit_filename_mask_mask
I cannot create a SSCE since there seems to be no difference between the working and non working version. The only difference of note is that when modal dialog is first displayed edit_filename_mask_mask has a value but add_filename_mask_mask does not. However edit_filename_mask_mask continues to fail if I blank out edit_filename_mask_mask , and add_filename_mask_mask when has value.
What happens if you try some safety checks ?
function addToEditMask(select, mask)
{
var selectedValue = document.getElementById(select).value || "";
var textarea = document.getElementById(mask);
textarea.value = (textarea.value || "") + " + " + selectedValue;
}
Variable name is "selectedValue" and you call to "selectValue"
I have a form field:
<div class="form-group">
<label>Name</label>
<input type="text" name="name" class="form-control" ng-model="abc.user.name" ng-focus="abc.setFocus('name')" required>
</div>
What I need to do is set add a class to the parent element, here <div class="form-group">, when the input has focus and remove it when the field loses focus.
I know how to do this in jQuery, but not in an Angular way. I have many form fields that need to behave like this, so I'm trying to avoid setting a variable and looking for that with an ng-class. I'd rather have some way for the field to simple act on its parent, which I can use the same method in every form field.
A directive is possibly the simplest generic approach if all you need to do is manipulate the dom.
<div class="form-group" focus-class="focused">
<label>Name</label>
<input name="name" class="form-control" ng-model="abc.user.name" required>
</div>
JS
angular.module('myApp').directive('focusClass', function(){
return {
link:function(scope, elem, attrs){
elem.find('input').on('focus', function(){
elem.toggleClass(attrs.focusClass);
}).on('blur', function(){
elem.toggleClass(attrs.focusClass);
});
}
}
});
You can perform this
<div class="form-group {{focusIsSet ? 'is-focused': ''}}">
<label>Name</label>
<input type="text" name="name" class="form-control" ng-model="abc.user.name" ng-focus="focusIsSet = true" ng-blur="focusIsSet = false" required>
</div>
Where $scope.focusIsSet a boolean property. So depends of its state you can manage classes in <div class="form-group"> with that expression {{focusIsSet ? 'is-focused': ''}}
You change it with ng-focus and ng-blur directives
UPDATE
I think you can hold states for each input with that way
<div class="form-group {{checkFocusState('abc.user.name') ? 'is-focused': ''}}">
<label>Name</label>
<input type="text" name="name" class="form-control" ng-model="abc.user.name" ng-focus="setFocus('abc.user.name')" ng-blur="setBlur('abc.user.name')" required>
</div>
</div>
JS code
var inputsFocusState = {};
$scope.checkFocusState = function(propertyPathName) {
if(inputsFocusState[propertyPathName] == true) {
return true;
}
return false
}
$scope.setBlur = function(propertyPathName) {
inputsFocusState[propertyPathName] = false;
}
$scope.setFocus = function(propertyPathName) {
inputsFocusState[propertyPathName] = true;
}
Otherwise, you can create each focus property for each input in html template
P.S. ng-class is good option too
P.S.S I had similar case, but forms were completely dynamic.
So I split each property in object like user.name = {value: 'john', buttons: [...], label: 'Name', //and much more}.
Also better to change 'user.name.path' to something like 'user-name-path'.
I have a combo box and I am trying to set the selected value from the controller. How can I do that?
<md-select ng-model="selectedControl" ng-change="changeControl(selectedControl)" required>
<md-option ng-repeat="control in controls" ng-value="control">{{control}}</md-option>
</md-select>
I tried:
$scope.selectedControl = "Test";
Control array:
[{"ControlId":1,"ControlColumn":"Address","ControlText":"AddressTest"},{"ControlId":2,"ControlColumn":"City_State_Zip","ControlText":"CityTest"}]
in your options just pass the index of value<md-option ng-repeat="control in controls" ng-value="control" ng-selected="index == 1">control</md-option>
this will select the scond value in array so you can modify it accoding to your requirement.
problem lies in your data array as you need to select the value itself from the array to be selected in options, try to get proper array or split the data for better control over drop down selection.
Working jsfiddle
<div ng-app="myApp" ng-controller="MyCtrl">
<div class="col-xs-12">
<label class="col-xs-6 control-label">Type:</label>
<div class="col-xs-6">
<select name="type" ng-model="selectedControl" ng-dropdown required ng-change="changeControl(selectedControl)" ng-options="control.ControlText for control in controls">
</select>
</div>
</div>
</div>
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.controls = [{ 'ControlId': 1, 'ControlColumn': 'Address', 'ControlText': 'AddressTest' }, { 'ControlId': 2, 'ControlColumn': 'City_State_Zip', 'ControlText': 'CityTest' }];
$scope.selectedControl = $scope.controls[1]; // change the value from here
}
I'm trying to create a form where, if the user selects 'yes' from a dropdown, two extra fields appear. Both of these fields are required, and one of them needs to be validated according to an array of 'codes' - the user must input one of the codes in the array for the form to submit correctly. However, if the user selects 'no' from the dropdown, these fields do not appear and are not required, and the array validation does not occur and the form can be submitted.
I have some code for this, however I can't get the fields to appear. An earlier issue I encountered with this (minus the array validation - including that broke the code and stopped the extra fields appearing) was that if the user selected 'yes', and then went back to change their mind and selected 'no', then the form would not submit, clearly still requiring the fields to be filled in/correct array value inputted.
If anyone could help me in making this work I would greatly appreciate it.
HTML:
<form id="form" method="post" action="action.php">
<div class="form-group">
<label class="control-label">Defect?</label>
<select onclick='checkIfYes()' class="select form-control" id="defect" name="defect">
<option id="No" value="No">No</option>
<option id="Yes" value="Yes">Yes</option>
</select>
</div>
<div id="extra" name="extra" style="display: none">
<label class="control-label" for="desc">Description</label>
<input class="form-control" type="text" id="desc" name="desc" required disabled>
<label class="control-label" for="auth_by">Authorised By</label>
<input class="form-control" type="text" id="auth_code_input" name="auth_by" required disabled>
</div>
<hr>
<div class="form-group">
<button class="btn btn-info" id="submit" name="submit" type="submit">Submit
</button>
</div>
</form>
JavaScript:
$(document).ready(function() {
checkIfYes = function checkIfYes() {
if (document.getElementById('defect').value == 'Yes') {
// show extra fields & make them required
document.getElementById('extra').style.display = '';
document.getElementById('auth_code_input').disabled = false;
document.getElementById('desc').disabled = false;
// show user if their input is one of the codes in the array when leaving field
$('#auth_code_input').blur(function() {
if (!ValidateInput()) {
e.preventDefault();
}
});
// prevent form submission if input is not one of the codes in the array
$('#auth_form').on('submit', function(e) {
if (!ValidateInput()) {
e.preventDefault();
}
});
function ValidateInput() {
var codes = ['Foo', 'Bar']; // user must enter one of these
var IsValid = false;
var input = $('#auth_code_input').val()
if (codes.indexOf(input) > -1) { // if input equals one of the codes in the array
$('#iconBad').removeClass('glyphicon-remove').addClass('glyphicon-ok');
IsValid = true;
} else {
$('#iconBad').removeClass('glyphicon-ok').addClass('glyphicon-remove');
IsValid = false;
}
return IsValid;
}
} else { // hide and disable extra fields so form can submit
document.getElementById('extra').style.display = 'none';
document.getElementById('auth_code_input').disabled = true;
document.getElementById('desc').disabled = true;
}
}
});
JSFiddle
It's a glitch in the way you define the function -- by calling checkIfYes() it's looking for it on the global (window's) scope. By changing the line:
function checkIfYes() {...
to this:
checkIfYes = function() {...
then you've got it on the global scope. Which is, by the way, bad practice. You'd be better to create a click handler in your script itself, than to hard- code the function call in your HTML. But that's just me.
A few changes made, some pretty significant -- first, I removed the hard-coded reference to checkIfYes and simply put the event in your javascript. Second (and pretty darn significant), I moved the event handlers to the root of your javascript, rather than defining them in your checkIfYes function. This way, they don't depend on that being called each time. Try it, it works.
$(document).ready(function() {
/**
* Define some custom events to handle...
**/
$("#defect").on("change", checkIfYes );
// show user if their input is one of the codes in the array when leaving field
$('#auth_code_input').blur(function() {
if (!ValidateInput()) {
console.log("Input is wrong!");
}
});
// prevent form submission if input is not one of the codes in the array
$('#auth_form').on('submit', function(e) {
e.preventDefault();
console.log("This is where I would be checking...");
if (ValidateInput()) {
$("#auth_form").submit();
}
});
// Utility Functions.
function checkIfYes() {
if (document.getElementById('defect').value == 'Yes') {
// show extra fields & make them required
document.getElementById('extra').style.display = '';
document.getElementById('auth_code_input').disabled = false;
document.getElementById('desc').disabled = false;
} else { // hide and disable extra fields so form can submit
document.getElementById('extra').style.display = 'none';
document.getElementById('auth_code_input').disabled = true;
document.getElementById('desc').disabled = true;
}
}
function ValidateInput() {
var codes = ['Foo', 'Bar']; // user must enter one of these
var IsValid = false;
var input = $('#auth_code_input').val()
if (codes.indexOf(input) > -1) { // if input equals one of the codes in the array
$('#iconBad').removeClass('glyphicon-remove').addClass('glyphicon-ok');
IsValid = true;
} else {
$('#iconBad').removeClass('glyphicon-ok').addClass('glyphicon-remove');
IsValid = false;
}
return IsValid;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="form" method="post" action="action.php">
<div class="form-group">
<label class="control-label">Defect?</label>
<select class="select form-control" id="defect" name="defect">
<option id="No" value="No">No</option>
<option id="Yes" value="Yes">Yes</option>
</select>
</div>
<div id="extra" name="extra" style="display: none">
<label class="control-label" for="desc">Description</label>
<input class="form-control" type="text" id="desc" name="desc" required disabled>
<label class="control-label" for="auth_by">Authorised By</label>
<input class="form-control" type="text" id="auth_code_input" name="auth_by" required disabled>
</div>
<hr>
<div class="form-group">
<button class="btn btn-info" id="submit" name="submit" type="submit">Submit
</button>
</div>
</form>
Alright so I have a form. In the form I have a lot of check boxes. If a person clicks on the checkbox. It shows the field below the box. If they click on the checkbox again it makes the field below the checkbox disappear and makes the field have no value.
here is the code. I have JS running the show and hide. and Html calling it.
function ShowCutSewDescription() {
var select = $('#send_item_to_cutsew');
console.log(select)
//select = parseInt(select);
if (select.attr('checked', true)) {
$('#cutsew-checked').show();
}else {
$('#cutsew-checked').hide();
}
}
<div class="form-group">
<label class="col-md-3 control-label">Sending item to Cut/Sew Manager</label>
<div class="col-md-9">
<input type="checkbox" name="send_item_to_cutsew" class="form-control input-inline input-medium" placeholder="Enter text" onchange="ShowCutSewDescription()">
</div>
Changes made
► select.attr('checked', true) to select.is(":checked")
► $('#send_item_to_cutsew') to $('[name="send_item_to_cutsew"]') since there is no element with that Id.
Working Demo
function ShowCutSewDescription() {
var select = $('[name="send_item_to_cutsew"]');
if (select.is(":checked")) {
$('#cutsew-checked').show();
} else {
$('#cutsew-checked').hide();
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="form-group">
<label class="col-md-3 control-label">Sending item to Cut/Sew Manager</label>
<div class="col-md-9">
<input type="checkbox" name="send_item_to_cutsew" class="form-control input-inline input-medium" placeholder="Enter text" onchange="ShowCutSewDescription()">
</div>
<div id="cutsew-checked">
Sample box
</div>
I assume this is using jQuery. If so, the selector that you have input is looking for something with an id of send_item_to_cutsew.
jQuery uses css selectors as a base, as referenced by this page: https://api.jquery.com/category/selectors/
The proper way to get the input that you want based on the name is as follows:
var select = $('[name="send_item_to_cutsew]');
or you can set the id to the above like so:
<input type="checkbox" id="send_item_to_cutsew" name="send_item_to_cutsew" class="form-control input-inline input-medium" placeholder="Enter text" onchange="ShowCutSewDescription()">