AngularJS ng-class remove class - javascript

I have the following code that is causing me meaningless pain
<input type="text" ng-class="GLOBAL_ERROR == 1 ? 'error-branch' : 'defaulttxt'" ng-model="frm.FirstName" name="FN" ng-required="true" ng-minlength="2" ng-maxlength="100"/>
When the page is loading the form is invalid so the class is error-branch after the data is loaded though the class does not change to defaulttxt
How do you fix this? Should i use something like the following?
$scope.$on('$viewContentLoaded', function(){
});

First of all thanks to #dfsq i realized the solution while replicating the issue on plunkr
the solution is to add one more condition to the GLOBAL_ERROR ==1 and it is
GLOBAL_ERROR==1 && myForm.FN.$invalid
Case closed damnnn

Related

Execution of code which is inside ng-if when it is false

Imagine I have code like this:
<span>Do you like bananas?</span>
<input type="radio" ng-model="likeBananas" name="likeBananas" value="yes">
<input type="radio" ng-model="likeBananas" name="likeBananas" value="no">
<div ng-if="likeBananas === 'no'">
<label>Tell us why?</label>
<textarea ng-model="whyNot" ng-required="likeBananas === 'no'"></textarea>
</div>
The idea is: if user don't like bananas, <textarea>with explanation is required. If user like bananas, of course it is not required and it's not shown to user. Because mandatory ot this field is dynamic, I used ng-required="likeBananas === 'no', but question is - do I really need it? Maybe simple required can do a job? Because, when ng-if is false, content of div should not be present in HTML. General question is - how Angular execute code inside elements with ng-ifs directive, from top to bottom or from bottom to top? In first case, code inside elements with ng-ifs when it's false should not be executed and, with case above, ng-required is not calculated when div is not present and maybe isn't needed. I hope you would help me with my doubts - thank you in advance.
No, you should use simply ng-required=true into a ng-if directive (in your case), because this directive behavior is removing/adding from the DOM the elements in it when the condition switch.
Thus, if likeBananas !== 'no', the elements
<label>Tell us why?</label>
<textarea ng-model="whyNot" ng-required="likeBananas === 'no'"></textarea>
are not included in the DOM, so the ng-require=true is not compiled.
please have a look here in the plunker:
http://plnkr.co/edit/fqoUbTXICDv0nNQe9aOL?p=preview
by making a form element, you can check it's validity, by doing:
Is the form valid? {{banana.$valid}}

How to combine ng-message messages

I am new to AngularJS but I have searched extensively and could not find a working answer to this question, maybe its just not possible the way I have it in mind.
What I would like is to be able to combine error conditions so that I can use more generic error messages in the ng-messages module. This saves us a lot of time maintaining texts as our application is multi-lingual. In my example it would be great to combine minlength, maxlength, and pattern and have it reference 1 generic message. The only way I have gotten it to work is for a separate ng-message for each type and then reuse the error text which seems redundant to me. Hopefully it's something short I am missing like not understanding when/how to use , or ||.
<form id="myFormId" name="myForm" novalidate>
<input name="sText" ng-model="someText"
type="text"
required
ng-minlength="8" minlength="8"
ng-maxlength="8" maxlength="8"
ng-pattern="/^[a-zA-Z0-9]{8,8}$/" pattern="/^[a-zA-Z0-9]{8,8}$/">
<div ng-messages="myForm.sText.$error" role="alert">
Error message:
<div ng-message="required">Required text missing</div>
<div ng-message="minlength || maxlength || pattern">Not right length or bad pattern - Why does this not work? I have also tried using comma , instead of || </div>
<div ng-message="minlength">Too short - this does work but does not change even if this is removed</div>
</div>
</form>
I have created this simple Plunk to illustrate what I am trying to do:
EDIT 1
I do realize I could use a single regex pattern expression but the above validations is strictly to reproduce the issue and show an example. I have other validations I would like to combine that could not be expressed with a single pattern.
ng-messages will show error message inside ng-messages directive element, but that has limitation that you could only display single error ng-message inside the ng-messages div.
So if you wanted to show multiple ng-message inside ng-messages directive you need to add ng-messages-multiple attribute on ng-messages directive element.
Docs Link
Markup
<div ng-messages="myForm.sText.$error" role="alert" ng-messages-multiple>
Error message:
<div ng-message="required">
Required text missing
</div>
<div ng-message="minlength, maxlength, pattern">
Not right length or bad pattern - Why does this not work? I have also tried using comma , instead of ||(OR)
</div>
<div ng-message="minlength">
Too short - this does work but does not change even if this is removed
</div>
</div>
Working Plunkr
Update
After angular document updation I came to know that ng-messages doesn't support to show multiple ng-message error inside ng-messages, for solving this problem we should have ng-messages-multiple attribute on ng-messages element.
From Docs
By default, ngMessages will only display one error at a time. However, if you wish to display all messages then the ng-messages-multiple attribute flag can be used on the element containing the ngMessages directive to make this happen.
Markup
<div ng-messages="myForm.sText.$error" role="alert" ng-messages-multiple>
Error message:
<div ng-message="required">
Required text missing
</div>
<div ng-message="minlength, maxlength, pattern">
Not right length or bad pattern - Why does this not work? I have also tried using comma , instead of ||(OR)
</div>
<div ng-message="minlength">
Too short - this does work but does not change even if this is removed
</div>
</div>
Working Plunkr
In Angular 1.4 you can specify multiple errors for a ng-message:
<div ng-message="minlength, maxlength">
Your email must be between 5 and 100 characters long
</div>
See documentation
Inorder to make your ng-message more generic you can keep all your error messages at one place and use it when required. You could do this using ng-message-include.
Have a look at : Reusing and Overriding Error Messages
http://www.yearofmoo.com/2014/05/how-to-use-ngmessages-in-angularjs.html#reusing-and-overriding-error-messages.
I think you will like to implement this.

jQuery find() returning undefined

I have a pretty typical form with some inputs and a submit button, however when I try to use jQuery's find() method, I get some annyingly inconsistent results. The are as follows:
$("#frmContact").find(":submit") -> undefined is not a function
$("#frmContact").find(".btn") -> works
$("#frmContact").find(".btn.secondary") -> undefined is not a function
$("#frmContact").find("input[type=submit]") -> works
$("#frmContact input:submit") -> undefined is not a function
$("input[type=submit]", "#frmContact") -> undefined is not a function
$("form").find("input") -> works
$("form").find("input[type=submit]") -> undefined is not a function
What's going on here and how do I fix this?
I'm using jQuery 1.11 after upgrading from 1.9 hoping that it will fix the issue. There's also Angular on the page and I'm calling this code from the console after everything is loaded.
My form, just in case you need it is as follows [EDIT] updated to show actual HTML output with Angular classes and directives:
<form ng-submit="saveContact($event, '/applicants/update_contact?id=1593')" class="ng-pristine ng-valid" _lpchecked="1" id="frmContact">
<h4 class="section-header">Applicant Contact Information</h4>
<field id="email" type="text" model="applicant.email" label="Email address" class="ng-isolate-scope">
<div ng-class="['field', isRequired()]" class="field"> <!-- Text/File/Password Field -->
<label ng-bind="label" class="ng-binding">Email address</label>
<input type="text" ng-model="model" class="ng-pristine ng-valid">
</div>
</field>
<div class="field">
<input type="submit" value="Save" class="btn secondary">
</div>
</form>
My JavaScript libraries are loaded in this order:
jQuery 11
jQuery UI
Angular
My app.js
Scripts are loaded at the bottom of the page.
AngularJS comes with JQLite, a lightweight smaller verison of jQuery, which is the one you are using here and that gives you unexpected results.
In order for Angular to works with the full jQuery, you need to make sure that you load jQuery before Angular. So watch your <script> tags order.
So it turns out the hand that held the knife to my throat was my own.
Earlier in the application's development it was useful to add a couple helper methods on the Object prototype by doing Object.prototype.findId = function() { ... }. Turns out this raised all sorts of hell when trying to perform the find() method in jQuery.
I fixed it by turning this:
Object.prototype.myMethod = function() { ... }
into this
var specialObject = function(object) {
return {
myMethod: function() { ... }
}
}
I didn't realize that my earlier approach was such bad practice until I read this: Extending Object.prototype JavaScript
Thank you all for your help, guys.

Angularjs ng-model is undefined

In HTML I have this line of code:
<input type="text" class="training-comment" placeholder="Enter comment" ng-model="content" data-ui-keypress="{13:'keypressCallback($event)'}">
And in controller this:
$scope.keypressCallback = function ($event) {
console.log("comment is", $scope.content);
$event.preventDefault();
};
And when I enter some text in input and press enter in console I see that $scope.content is undefined.
Why is this ?
I put together a Plunker example here using the Angular UI and basically copying the code from the question. I then took this example and added an ng-repeat to demonstrate one of the most common issues I have seen: scope issues:
<div ng-repeat="x in collections">
<input type="text" class="training-comment" placeholder="Enter comment"
ng-model="content" data-ui-keypress="{13:'keypressCallback($event)'}" />
<br /><br />
</div>
You can find this updated plunker example here. Basically whenever you use an ng-repeat or any other directive that creates a new scope your model exists in that scope - not the parent or root scope. This means that your code might be working, but it is printing out the value from the wrong scope! For more information on scopes see the angular documentation here.
To use the plunker demo, type into the first input and press the enter key, the model will be updated. But, if you type into either of the other two boxes, though, the model will either not be updated or it will be undefined (if you have never typed into the first box).
Even if this isn't the exact issue, hopefully it will still help. Best of luck!

Chrome and oninput events

I have a textbox, and I am trying to fire an event oninput (my example below only removes a comma from the input, however I do need it to do more advance things). My code works great on Firefox and Internet Explorer, however when I click into the textbox in Chrome, I have about .5 seconds to start typing, otherwise I loose focus. Testing the exact code below on my website creates the error. Any idea?
<input type="text" id="question" name="question" oninput="clean(this);" />
<script type="text/javascript">
function clean(q){
q.value=q.value.replace(",","");
}
</script>
Thanks for any help
Credit goes to ComFreek and RobH for pointing it out that it works just fine on JS fiddle. I feel quite dumb for not trying it first. Turns out that some of the other Javascript on the page was causing the trigger to break. Thanks for everyone's help!
You can try to set a timer to run the code in the function.
<input type="text" id="question" name="question" oninput="clean(this);" />
<script type="text/javascript">
function clean(q){
window.setTimeout(function(){
q.value=q.value.replace(",","");
}, 0);
}
</script>
Try to use <input onkeyup="clean(this)">, it will only fire the function after something is typed into the input.
http://www.w3schools.com/jsref/event_onkeyup.asp
If you are going to do some complex things I'd recommend you use jQuery, because will fix this crossbrowser errors.
and use something like:
$('#input-desired').bind('keyup', function() {
this.value = this.value.replace(',', '');
});
If you wanna go for a simple application you can try this.
<input type="input" id="desired" onkeyup="desiredInputChanges(this);" />
In your Javascript file use something like:
desiredInputChanges = function (input) {
input.value = input.value.replace(',', '');
}
Just a note, don't forget to make a function to be your class and protect your methods :)

Categories