Angular appending html with directives from within a directive - javascript

I'm trying to write a small directive that will append the validation tags and ngMessages dynamically to the input. But I'm having trouble appending the ng-message attribute to the div.
The idea is to have this,
<div validator validations="{json_data containing error messages}">
<input name='fieldName'>
</div>
Turned in to the following according to the provided JSON.
<div validator>
<input required="required"></input>
<div ng-message="fieldName" ng-if="fieldName.$dirty>
<p ng-message="required"> scope.message </p>
</div>
</div>
I've currently managed to get the ng-required appeneded using the answer to this answer. But I can't seem to append the ng-message tag using the same technique. What should be done differently to solve this issue?
The final directive should be able to generate something like this Fiddle
The current version can be found in the Fiddle here the example works as expected until 'scope' is added. But as soon as 'scope' is added, the example stops working.
Update
I've realized that this only occurse when you add a local scope. This error doesn't occure when using the global scope and accessing the variable using scope.$eval(attrs.message)

Related

Where to declare long ng-style attributes Angularjs

Say I have the following snippet in an Angular project:
<div ng-app="ExampleApp" ng-controller="ExampleController as controller" ng-init="">
<div ng-style="styleRules={'background-color':'blue', 'width':'100px', 'height':'100px'}"></div>
</div>
If "styleRules" contains a dozen or more CSS rules, should I still keep the entire JSON object in-line, or should it be moved to another file? If it should be moved, to where should I move it?
If it's primarily static as the example you provided, I'd recommend moving it to a $scope.styleRules variable in your script and referencing it in ng-style="styleRules".
Update
Actually if it's static, just put the rules in the style attribute. While not required, you only need to include the dynamic rules in ng-style.

AngularJS Ng-repeat, create dynamic dom with expressions

Here is The problem i am trying solve. I would like to create a JS script that uses angular to dynamically create div elements while adding an additional expression eg {{levelone}}.
Here is an an example of what i am expecting the output to be if i know i have 5 iterations of Dom elements.
<div ng-switch-when="0">{{levelZero}}</div>
<div ng-switch-when="1">{{levelOneA}}{{levelOneB}}</div>
<div ng-switch-when="2">{{levelTwoA}}{{levelTwoB}}{{levelTwoC}}</div>
etc.....
So as you can see i am adding an expression on each time. I just dont know how i can keep adding them on via a repeat loop and then get them to compile correctly with AngularJS. I am trying to make my DOM as Dynamic as possible.
EDIT
Every time i loop 1 more i am adding an expression ->{{expression}} to the div with JS or angular. I am not hard coding the expression into each div as each div is also dynamically created. But with a twist i am adding that extra expression ie 3 expressions from the previous div and adding one more expression making four. see example below.
<div ng-switch-when="3"{{levelTwoA}}{{levelTwoB}}{{levelTwoC}}</div>
This one below is dynamically generated
<div ng-switch-when="4"{{levelTwoA}}{{levelTwoB}}{{levelTwoC}}{{THIS EXPRESSION IS GENERATED IN js AND ADDED & COMPILED}}</div>
The DOM will be dynamic as long as your data bindings are. I need more info (data model, expectations) to be more accurate but if you set up your data and bind it correctly, it should work. for example if your data looked like this
var data = {
"levelOne" : {},
"levelTwo" : {
"elements" : ["<span id="firstEl"></span>, ...]
},
"levelThree" : {
"elements" : ["<span id="firstEl"></span>, <span id="secondEl"></span>, ...]
}
Then in your template do what #paulgoblin suggested.
}
You could ng-repeat within each switch case. Eg.
<div ng-switch-when="0">
<span>{{levelZero}}</span>
</div>
<div ng-switch-when="1">
<span ng-repeat="expression in levelOne">{{expression}}</span>
</div>
<div ng-switch-when="2">
<span ng-repeat="expression in levelTwo">{{expression}}</span>
</div>
You might want do this with scope function.
<div ng-switch="assignment.id">
<div ng-switch-when="1">{{ getExpressions(assignment.id) }}</div>
<div ng-switch-when="2">{{ getExpressions(assignment.id) }}</div>
</div>

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.

Why I can't access a form object inside a ngInclude on angularJS?

I have a screen built with a several stacks of ng-includes. The last one, in special, I build the screen based on user configuration.
Sometimes, I have to show a Form in one of this included templates. And when my user click on save button, I have to validate if all fields in the form are valid.
In the meantime, when a try to access form object, to check for $valid, my form is undefined.
After a day fighting against it, I've discovered that ng-include process is not accepting my form object to be created.
I've created this plunker to see if it's really happening on a simple project, making a working form and not working one:
http://plnkr.co/edit/4oMZYLgaYHJPoSZdSctI?p=preview
Basically, created a form, like this, with demanded angular attributes:
<form name="sampleForm">
<input type="text" name="aws" required ng-model="myValue">
<br/>myValue: "{{ myValue }}"
<br/>
<input type="text" name="aws" required ng-model="myValue">
<br/>myValue: "{{ myValue }}"
</form>
And trying to access form object like this:
$scope.sampleForm.aws.$valid
And the result is:
$scope.sampleForm === undefined
Someone know how to solve this problem?
Since ng-include creates a new scope, $scope.sampleForm will be undefined from within the included page.
The solution should be getting the ng-controller="formController" declaration inside of the included HTML page itself, which I think is also a better design, since I can't see a scenario where it's not "controlling" the form.
The other non-included form obviously works as you might expect.
Plunker

ng-bind-html does not work

please look at this fiddle
please type 4 in the text area,
it should write an error message, that is in this line:
$names.push('<div ng-bind-html-unsafe="snippet"></div>');
actually it does not. It prints the html code itself without handling,
and the underlying html is:
<li ng-repeat="user in list|splitList:appUsers" class="ng-scope ng-binding">
<div ng-bind-html="snippet"></div>
</li>
I tried to follow solutions from this topic
but nothing seem to help,
any help in fixing it will be regarded,
I got help from the chat room of angularjs,
the thing is that I should use:
<div ng-bind-html-unsafe="user">...</div>
instead of {{user}}
To get it to work you will need the following:
Declare it in html
div ng-bind-html="{expression}"></div>
Or
div class="ng-bind-html: {expression};"></div>
AND
reference angular-sanitize.min.js and then add
angular.module('YOUR_APP_NAME', ['ngSanitize']);
The last two are in the angularjs documentation for some reason...

Categories