I currently have the cursor auto-focus to a particular field which works as expected (when the modal is displayed). The problem is when i click on another field in that same form and begin typing, the cursor jumps back to the initial field with the autofocus attribute. Any idea what's causing this? thanks in advance
This is for an angular 1.7 project. I have tried moving the autofocus function to different locations within the controller, none of which made a difference.
//Controller
angular.module('qmsControllers').controller('ResponseCodesModalCtrl', function($scope) {
$scope.giveFocus = function() {
$(**'#responsecode'**).focus();
return true;
};
});
//view
<div class="form-group modal-form-group">
<label for="code" class="col-sm-2 control-label">Response Code:</label>
<input type="text" class="some class="0 === editMode"
ng-change="onResponseCodeChanged($event)"
**id="responsecode"**
**ng-show="giveFocus()"**
name="code" ng-model="response" />
</div>
The expected result is the autofocus occurring when the modal is displayed but allowing for typing in fields other than the autofocus field.
ng-show does not mean what you might think it means, ng-show controls whether or not the element should be shown, not "execute this function when I'm shown"
So each time angular evaluates if the input element needs to be shown your element triggers an onFocus.
If you want to trigger the focus only when loading the dialog you could simply call
$scope.giveFocus() at the end of the controller function. And remove the ng-show attribute
you can also use the $onInit method this method will be called by angularjs once the view has been initialized, it maybe that the element isn't in the dom yet.
So something like
this.$onInit = function() {
$(**'#responsecode'**).focus();
};
Related
I am working for the first time with reactive forms in Angular(v7)
I want to make my submit button enabled if any of the fields has changed. So I am working with the dirty value of the form.
For a simple scenarios its working. I change a input type text and the button became enable.
But now I got a problem with an element (<span id="locationUpdated">) that the value inside of it is being changed by the result of some other javascript functions.
So I decided to listening the change of an hidden input that get the value the same way as the span element
<form [formGroup]="model.form" >
....
<input id="nameInput" type="text"
[(ngModel)]="model.user.name"
formControlName="name" />
...
<span [textContent]="model.user.location.label" id="locationUpdated"></span>
<input type="hidden" [value]="model.user.location.label" formControlName="location" />
....
<button [ngClass]="{'disabled': !model.form.dirty}></button>
</form>
--- Component ---
private buildFormUpdated() {
this.model.form = this.formBuilder.group({
name: [this.model.user.name, [Validators.required]],
location: [this.model.user.location.label]
});
}
I replace the hidden to text so I can see the value change and it is working fine.
However the property dirty continues false. If I change manually I get the dirty:true
What am I missing?
Thanks
What am I missing?
The dirty flag is not set to true when the data is changed programatically.
It is set to true only if the user blurs the control component, or changes the value (through the UI)
Please ref official docs - https://angular.io/guide/form-validation#why-check-dirty-and-touched
you can explicit marks the control as dirty by doing this after your logic
this.model.form.markAsDirty();
I am new to angularjs and I am trying to create a form page with some animations.
I am trying to tweak the code from fiddle here - http://jsfiddle.net/atXAC/11/
<div ng-class="{'active':hasFocus==true,'inactive':hasFocus==false}">Enter your Name here</div>
<input type="text" ng-model="user.name" ng-click="hasFocus=true" ng-customblur="onBlur()" required id="name"/>
Currently, on click and on click away the css class is changed.
What i am trying to do is when something is entered in the box the class should not change. If the text box is empty then only the class should be changed on- click-away. How do i do this? any help much appreciated.
Thanks in advance.
If i understood correct,your Controller should be like this.
function MyCtrl($scope) {
$scope.onBlur = function(){
if(user.name=="")
$scope.hasFocus = false;
}
}
JSFiddle here: http://jsfiddle.net/c6tzj6Lf/4/
I am dynamically creating forms and buttons and want to disable the buttons if the required form inputs are not completed.
HTML:
<div ng-app="choicesApp">
<ng-form name="choicesForm" ng-controller="ChoicesCtrl">
<div ng-bind-html="trustCustom()"></div>
<button ng-repeat="button in buttons" ng-disabled="choicesForm.$invalid">
{{button.text}}
</button>
</ng-form>
</div>
JavaScript:
angular.module('choicesApp', ['ngSanitize'])
.controller('ChoicesCtrl', ['$scope', '$sce', function($scope, $sce) {
$scope.custom = "Required Input: <input required type='text'>";
$scope.trustCustom = function() {
return $sce.trustAsHtml($scope.custom);
};
$scope.buttons = [
{text:'Submit 1'},
{text:'Submit 2'}];
}]);
choicesForm.$invalid is false and does not change when entering text into the input field.
Solution:
I ended up using the angular-bind-html-compile directive from here: https://github.com/incuna/angular-bind-html-compile
Here is the relevant bit of working code:
<ng-form name="choicesForm">
<div ng-if="choices" bind-html-compile="choices"></div>
<button ng-click="submitForm()" ng-disabled="choicesForm.$invalid">
Submit
</button>
</ng-form>
And choices might be a snippit of HTML like this:
<div><strong>What is your sex?</strong></div>
<div>
<input type="radio" name="gender" ng-model="gender" value="female" required>
<label for="female"> Female</label><br>
<input type="radio" name="gender" ng-model="gender" value="male" required>
<label for="male"> Male</label>
</div>
The main problem is that ngBindHtml doesn't compile the html - it inserts the html as it is. You can even inspect the dynamic input and see that it doesn't have the ngModel's CSS classes (ng-pristine, ng-untouched, etc) which is a major red flag.
In your case, the form simply doesn't know that you've added another input or anything has changed for that matter. Its state ($pristine, $valid, etc) isn't determined by its HTML but by the registered NgModelControllers. These controllers are added automatically when an ngModel is linked.
For example this <input required type='text'> won't affect the form's validity, even if it's required, since it doesn't have ngModel assigned to it.
But this <div ng-model="myDiv" required></div> will affect it since it's required and has ngModel assigned to it.
The ngDisabled directive on your buttons works as expected since it depends on the form's $invalid property.
See this fiddle which showcases how ngModel registers its controller. Note that the html containing the dynamic input gets compiled after 750ms just to show how NgModelControllers can be added after FormController has been instantiated.
There are a few solutions in your case:
use a custom directive to bind and compile html - like this one
use ngInclude which does compile the html
use $compile to compile the newly added HTML but this is a bit tricky as you won't know exactly when to perform this action
This is an answer yet imcomplete because i cannot do the code at the moment.
I think your html will be included, not compiled. So the inputs are not bind to angular and are not part of the angular form object.
The only way i see is to use a directive that will compile the passed html and add it to your form. This may be quite tricky though, if you want to go on this way i suggest to edit your question to ask for the said directive.
However i'm not really familiar with $compile so i don't know if it'll work to just add $compile around $sce.trustAsHtml()
You can write a method as ng-disabled does not work with booleans, it works with 'checked' string instead:
So on your controller place a method :
$scope.buttonDisabled = function(invalid){
return invalid ? "checked" : "";
};
And on your view use it on angular expression :
<button ng-repeat="button in buttons" ng-disabled="buttonDisabled(choicesForm.$invalid)">
Here is a working fiddle
Working DEMO
This is the solution you are looking for. You need a custom directive. In my example I have used a directive named compile-template and incorporated it in div element.
<div ng-bind-html="trustCustom()" compile-template></div>
Directive Code:
.directive('compileTemplate', function($compile, $parse){
return {
link: function(scope, element, attr){
var parsed = $parse(attr.ngBindHtml);
function getStringValue() { return (parsed(scope) || '').toString(); }
//Recompile if the template changes
scope.$watch(getStringValue, function() {
$compile(element, null, -9999)(scope); //The -9999 makes it skip directives so that we do not recompile ourselves
});
}
}
});
I found the directive in this fiddle.
I believe what is really happening though due to jsfiddle I'm unable to dissect the actual scopes being created here.
<div ng-app="choicesApp">
<ng-form name="choicesForm" ng-controller="ChoicesCtrl">
<div ng-bind-html="trustCustom()"></div>
<button ng-repeat="button in buttons" ng-disabled="choicesForm.$invalid">
{{button.text}}
</button>
</ng-form>
</div>
The first div is your top level scope, your form is the first child scope. Adding the div using a function creates the dynamically added input field as a child of the first child, a grandchild of the top level scope. Therefore your form is not aware of the elements you're adding dynamically causing only the static field to be required for valid form entry.
A better solution would be to use ng-inclue for additional form fields or if your form isn't to large then simply put them on the page or template you're using.
A few days back, I asked the following question:
I've searched for how to do this, and I've not had any luck. I'm fairly inexperienced with web stuff, so perhaps it's so trivial that no one needs to ask how to do it :(
Suppose I have an HTML text input field with a label, like this:
<label for = "stuff">Stuff</label>
<input type = "text" name = "stuffz" id="stuff" value = "hello!">
Now suppose the text input field value is changed. Is there a way to use AngularJS to restyle the label (Like, turn it green, for example) when this change occurs? I've looked into using ng-change and ng-class, but I'm not knowledgeable enough about how these work to use them in this manner.
When I tested the solution provided, which was:
CSS
.marvellous {
color: green;
}
HTML
<div ng-app="demo">
<label for="stuff" ng-class="{ 'marvellous' : !!hasChanged }">Stuff</label>
<input type="text" id="stuff" ng-model="myModel" ng-change="hasChanged = true"></div>
It worked, but only when I manually changed the text field (i.e. I typed stuff in the text field directly). However, in the particular application I'm working on, I need for the labels to be restyled when the value stored in ng-model changes. Unfortunately, I falsely assumed that if this method worked when I manually changed the text field, it must work if ng-model were to change as well. I've come to find out that it doesn't.
What's the reason for this? And how can I make the label re-style when ng-model changes?
Thanks!
EDIT: When I say "ng-model changes," what I mean is..in my controller, there is a variable that is used to populate the text fields of the app that I'm working on. However, when the user clicks an "import changes" button, this variable is changed according to the changes that they are importing, which consequently changes the corresponding text fields linked to that variable. Ultimately, I want all of the labels attached to these changed text fields to be highlighted for the user to see. I'm sorry for my vagueness.
Each input in an angular js form has meta data properties to help you. For example
<form id="form">
<label for="stuff" ng-class="{ 'marvellous' : form.stuff.$dirty}">Stuff</label>
<input type="text" id="stuff" ng-model="myModel" ng-change="hasChanged = true">
</form>
https://docs.angularjs.org/api/ng/type/form.FormController
You can achieve that using $scope.$watch :
function demoCtrl ($scope) {
$scope.$watch('myModel', function (newValue, oldValue) {
if (newValue) {
$scope.hasChanged = true;
}
});
$scope.changeMyModel = function () {
$scope.myModel = 'wonderful';
};
}
.marvellous {
color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="demoCtrl">
<label for="stuff" ng-class="{ 'marvellous' : !!hasChanged }">Stuff</label>
<input type="text" id="stuff" ng-model="myModel" ng-change="hasChanged = true">
<button ng-click="changeMyModel()">change model</button>
</div>
<!--Use ng-style !!! replace your lable with this--->
<label for="stuff" ng-style="hasChanged()">Stuff</label>
and define your function like this below---
$scope.hasChanged = function(){
if($scope.myModel !== initValue){
return { color: "green" }
}
}
I have a problem where I'm attempting to post the value of a checkbox in my model to the server and as the checkbox has not been interacted with on the form, angular seems to have not assigned it a value, when I ask for the value of the checkbox it comes back as undefined.
Here is my markup:
<div class="form-group">
<input id="templateDisable" type="checkbox" ng-model="template.disabled" />
<label for="templateDisable">Disabled</label>
</div>
And here's a reduced version of my save action on my controller:
$scope.save = function (form) {
if (form.$valid) {
var formData = new FormData();
// this is the problem line of code
formData.append("disabled", $scope.template.disabled);
// ... some other stuff
}
};
Actually, ticking then unticking the checkbox before I hit the save action results in the template.disabled property being false, which is what I would have expected without any manual intervention.
I've seen other related questions, e.g. AngularJS: Initial checkbox value not in model but surely stuff like a simple checkbox should be baked in? I shouldn't have to be writing directives to manage checkboxes surely?
This is per design. If you want a default value on your model than you should initialise it inside the controller (recommended), or make use of ng-init.
app.controller('AppController',
[
'$scope',
function($scope) {
$scope.template = {
disabled = false
};
}
]
);
<div class="form-group">
<input type="checkbox" ng-model="template.disabled" ng-init="template.disabled=false" />
<label>Disabled</label>
</div>
The following will always set the state back to "unchecked" when the page is loaded (or refreshed). In other words it will overwrite the user's actual selection whenever the page is refreshed.
<input type="checkbox" ng-model="template.disabled"
ng-init="template.disabled=false" />
If, however, you want the checkbox state set to a default state initially and you also want it to remember user interactions, then the following is what you want.
<input type="checkbox" ng-model="template.disabled"
ng-init="template.disabled = template.disabled || false" />