I am doing something like this, where I am declaring selectors on the fly.
<div ngFor="let x of y;let i = index;">
<input *ngIf="i === 0" #selector0 type="number" value="{{item.value}}">
<input *ngIf="i === 1" #selector1 type="number" value="{{item.value}}">
</div>
Is there a way to do it like below, where I don't need to repeat myself?
<input #selector{{i}} type="number" value="{{item.value}}">
<button (click)="submit(selector0)">
I'm not looking for an alternative way to do it, just wondering if dynamic selectors are possible.
So we start here, where Angular defines these as a "Template Reference Variable":
https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ref-vars
Okay, so let's try to find the source for that.
https://github.com/angular/angular/blob/master/modules/%40angular/compiler/src/template_parser/template_parser.ts#L34
https://github.com/angular/angular/blob/master/modules/%40angular/compiler/src/template_parser/template_parser.ts#L430
So we're trying to parse out the element... lets see how it defines that:
https://github.com/angular/angular/blob/master/modules/%40angular/compiler/src/template_parser/template_parser.ts#L16
I'm going to put a breakpoint and see what's up.
EDIT:
I put a breakpoint in the "_parseAttr" function to see what it sees when it looks at the template reference:
Here is the call to find the binding:
var hasBinding = _this._parseAttr(isTemplateElement, attr, matchableAttrs, elementOrDirectiveProps, animationProps, events, elementOrDirectiveRefs, elementVars);
And what the debugger outputs for the attribute name:
attr = Attribute {name: "#testerno{{check}}", value: "", sourceSpan: ParseSourceSpan, valueSpan: undefined}
So it looks like the attribute name name: "#testerno{{check}}" is not parsed to see if {{check}} is an angular variable, it just interprets that as part of the string.
Therefore, you cannot do what you put above. It thinks the reference name is "#testerno{{check}}" in this case.
Or, in your case, selector{{i}}.
Note that this makes sense because the "#" is used at the compiler level and is not present in your output html, so it would have no way of dynamically creating that reference.
Assign it to a data attribute, then you can use javascript's querySelector.
<input attr.input="{{i}}" type="number" value="{{item.value}}">
Related
I am new to javascript and angular so,i would appreciate your help, before I start plz have a look at below two pictures-
After some time there is a change-
Now some attributes in below HTML code has same attribute, -
<input type="text"
class="menuTitleField ng-pristine ng-untouched ng-valid ng-isolate-scope ng-valid-required"
ng-model="title" placeholder="Option Name" elastic-input=""
ng-required="isRequired" focus-on="newChild" focus-if="canFocus"
tabindex="0" required="required" style="min-width: 0px; width: 48px;">
For example, there are canFocus or title, in HTML and in above picture, so how can I get the value of canFocus, title using java script based on class name or tag name or event.target.id?
I think these values come from the sever, how can I get values of those attribute?
Plz, ask in comment for clarification, also edit the post for more precise question. thanks.
so how can I get the value of canFocus using java script
Use either:
$rootScope.canFocus
or
$scope.$root.canFocus
To use $rootScope,$scope in your controllers, you need to import it then you can use variables to get values like
$scope.title
$scope.canFocus
if you want to use $rootScope just use this
$rootScope.title
$rootScope.canFocus
In your HTML
title,canFocus should work with your code
Angular has an angular way of doing almost everything. In this instance I would suggest researching property binding. For example with the placeholder property you can write:
<input [placeholder]="someVariable">
Then declare the someVariable in your component and what ever you set it to will be the placeholder and you can access it that way. The [] lets you set it to a variable in your component and will update the placeholder whenever you change it in your component. I would try experimenting with this to get an understanding for how it works.
I have a form which contains a parent element and a child element, in every browser I can retrieve this value but in MS Edge I am unable to get the key from the parent element. Is anyone able to shed light on this issue?
<div v-for="(levelKey, level) in levels">
#{{ level.name }}
<div v-for="(currencyKey, currency) in currencies">
<input type="text" name="levels[#{{ level.id }}][currency.id]" v-model="...">
</div>
</div>
You can write your type attribute as a bound attribute using the :type syntax. See: https://vuejs.org/guide/syntax.html
Then you don't need the moustache braces (#{{ ... }}) when you're already inside an expression. You can just write:
<input :name="levels[level.id][currency.id]" v-model="...">
or even simpler (since you're already looping through levels):
<input :name="level[currency.id]" v-model="...">
EDIT
I created a JSFiddle with some mock data (probably not exactly the same as yours, though) and tried it in MS Edge. It worked fine:
Maybe you forgot to copy a part of the code?
I have an app with many forms. Each field has several HTML elements, so I thought I could extract some directives (one per type of field) to keep my forms tidy.
I've created a sample app to demonstrate the problem, but I'm getting inconsistent behavior. In the sample app, a <link /> element replaces the <input />. In my real app, <input /> just gets removed from the DOM completely. I feel like this should be easy; why doesn't it work?
To answer your stated question, it's because you told it to, with ng-transclude. That replaces the contents of the tag with the original element, which I don't think you wanted; you probably wanted the original contents to be transcluded as the label instead.
This is probably what you're looking for:
<div class="form-group" >
<label for="{{htmlId}}" ng-transclude></label>
<input id="{{htmlId}}" class="form-control" type="text" ng-model="model" />
<span ng-repeat="error in errors">{{error}}</span>
</div>
I've moved the tranclusion into the label. While this works, I would also recommend the style of actually passing a label attribute, rather than transclude it, just for the sake of having a consistent API and simpler code; it's functionally equivalent, though, so don't let me bully you.
Also, you've got a few errors in your .js as well. First, you want to use = in your scope instead of &
scope: {
model: '=',
errors: '='
},
& is used to pass methods, while = is used for objects (this is a simplification). Since your model and errors are objects, you'll want to use = instead.
Finally, in your example, your html template and your directive's template don't have the same name... you've got an extra 's' in your .js, but that's probably just in the plunker and not your real app.
I am using this jQuery validation library on my website. It requires me to put the validation rules in the class part of the input tag. ie <input class="validate[required,custom[onlyLetter],length[0,100]]" name="firstname" type="text" />
Now this causes me to end up with code in mine that looks similar such as:
<input type="text"
id="charfname"
name="charfname"
value=""
style="width: 300px;"
class="validate[required,length[3,20],custom[noSpecialCaracters]]" />
Which as you see has a [ and ] in the class name. So when I run the page through a validator I get the error:
character "[" is not allowed in the value of attribute "class"
How do I fix this to make it valid but still have the library work?
Thanks
Use some other method for initialization or use another script? Use an alternate attribute and a custom DTD for example. Or throw away the attribute based init system and use something else. Either way you have to modify the plugin's code. You cannot use "[" and "]" characters in a class name and any other combination implying them, period.
I'm looking to create a form which contains a dynamic number of input text boxes. I would like each text box to form part of an array (this would in theory make it easier for me to loop through them, especially as I won't know the number of text fields that will eventually exist). The HTML code would like something like:
<p>Field 1: <input type="text" name="field[1]" id="field[1]"></p>
<p>Field 2: <input type="text" name="field[2]" id="field[2]"></p>
<p>Field 3: <input type="text" name="field[3]" id="field[3]"></p>
<p>Field 4: <input type="text" name="field[4]" id="field[4]"></p>
<p>Field 5: <input type="text" name="field[5]" id="field[5]"></p>
This data would then be sent to a PHP script and would be represented as an array - or at least, that's the theory.
So my first question is, is this achievable using HTML? Are forms designed to work that way?
If the answer to that is "yes", how would I then go about accessing each of those using jQuery or failing that, plain old JavaScript?
I've attempted to achieve this using the following jQuery code:
someval = $('#field[1]').val();
and
someval = $('#field')[1].val();
and the following JavaScript:
someval = document.getElementById('related_link_url')[1].value;
But I've not had any luck.
Thanks in advance.
Edit:
I should note that from a Javascript point of view, I've had it working where the ID of each element is something like field_1, field_2 etc. However, I feel that if I can achieve it by placing each text box into an array, it would make for tidier and easier to manage code.
Give each element a class and access the group using jQuery:
<p>Field 1: <input type="text" name="field[1]" class="fields"></p>
<p>Field 2: <input type="text" name="field[2]" class="fields"></p>
<!-- etc... -->
jQuery:
$("input.fields").each(function (index)
{
// Your code here
});
This will run the anonymous function on each input element with a classname of "fields", with the this keyword pointing to the current element. See http://api.jquery.com/each/ for more info.
First of all, id attribute cannot contains [ or ] character.
There is lots of ways to get jQuery/plain JavaScript references to these elements. You can use descendant selector:
<fieldset id="list-of-fields">
<!-- your inputs here -->
</fieldset>
$("#list-of-fields input");
document.getElementById("list....").getElementsByTagName("input");
You can also use attribute selector:
$("input[name^=field]");
I'm not sure whether that's the only way but I think in plain JavaScript you'll have to fetch all input elements (document.getElementsByTagName) and then loop through array of these elements and check each element (whether it has name attribute which value starts with field).