How to make multiple instances of the same Angular 2 component work properly in the same container - html

I have component <editor [id]="id"> template like
<input id="name" />
<label for="name"></label>
and using it with CSS framework like MaterializeCSS which binds labels to inputs using unique HTML DOM id attribute.
Now, If I do this:
<div *ngFor="let someThing of listOfSomeThings">
<editor [id]="someThing.id"></editor>
</div>
angular generates many components with the same id, so id attribute is not encapsulated at all and components begin to conflict with each other.
I found a solution by doing this:
<input [id]="id + 'name'" />
<label [for]="id + 'name'" />
But this looks bad and leads to less maintainable code. Is there any neater and finer way to write fully-encapsulated-dom components (maybe some internal Angular 2 function that I just need to enable)? Or am I to write all components in this way to ensure that it will never conflict in such situations?

You could use UUID generator for ids or just big random number.

Related

angular survey dynamic questions rendering template driven or reactive

I am new at angular currently started a project with angular 9 to build survey application where I have
dynamic questions with
different question type (radio,checkbox, textbox, textarea, dropdown,etc)
question options (dynamic for each question)
dynamic attributes like (required, minlength, maxlength, pattern, data-attributes)
I started with template driven form, but having issues with attribute, multiple checkboxes and may face more issue in future
while reactive Forms looks too much complex
Looking for expert suggesion which method should I follow
currently at teplate driven forms to render checkboxes I wrote this code
<!--checkbox type=2 -->
<div class="optgroup" *ngSwitchCase="2">
<div *ngFor="let opt of question.QuestionOption; let io = index" class="form-check form-check-inline mx-3" >
<input type="checkbox"
name="data[{{survey.Survey.id}}][{{section.id}}][{{question.id}}][]"
[id]="'rdo'+is+iq+io"
value="{{opt.title}}"
class="form-check-input"
ngModel />
<label [for]="'rdo'+is+iq+io" class="form-check-label">{{opt.title}}</label>
</div>
</div>
I am able to select multiple checkboxes but at {{f.value | json}} only last changed value is coming as boolean but not array of select values.
and secondly how can add attribute dynamically
if(webservice.currentQuestion.attrubutes != null){
loop over attributes and
add each attribute to let's say above checkbox or <input type="text"> or <select>
}
have no idea how can add these dynamic attributes

ui-bootstrap datetime-picker define show-meridian to false

I'm using ui-bootstrap-datetime-picker with angularJS. And i'd like to know if it's possible to set show-meridian options of time-picker directly inside timepickerOptions ?
...
<input type="text" class="form-control"
datetime-picker="MM/dd/yyyy HH:mm"
timepickerOptions="{'show-meridian': 'false'}"
ng-model="ctrl.date.value"
is-open="ctrl.date.showFlag"/>
<span class="input-group-btn"></span>
...
This is a plnkr which illustrate the problem.
Root cause of the problem is wrong naming style. To make your code work, you have to change camel-case to dash-delimited: timepicker-options instead of timepickerOptions (see my forked plunker):
<input type="text" class="form-control"
datetime-picker="MM/dd/yyyy HH:mm"
timepicker-options="{'show-meridian': false}"
ng-model="ctrl.date.value"
is-open="ctrl.date.showFlag"/>
The key point here is normalization process being done by AngularJS. Since HTML is case-insensitive, AngularJS cannot convert HTML attribute named timepickerOptions into scope variable timepickerOptions - because timepickerOptions in HTML is seen by AngularJS exactly like timepickeroptions; so, there is no chance for it to determine how to normalize this name. Thus, you should always use -, _ or : to delimiter different words in directive name when using HTML.

Angular 2 - Basic form validation not working anymore

I have an angular 2 application which contains a basic form with inputs and basic html validation. Something like:
<form (onSubmit)="submit()">
<input type="email" />
<input type="submit" value="save" />
</form>
This worked about a week or two ago. Today, I was testing my application and noticed that it's completely ignoring any basic validation like type, pattern, max, min, etc.
In this case, it should complain when you type in a value without the # symbol. However, it isn't complaining anymore. You can type whatever you want in the input field.
Any idea how this could happen?
I was having this issue too. So I searched and found this.
Basically by default angular is adding something called novalidate.
If you guys want to use browser's native form validation just add ngNativeValidate attribute:
<form ngNativeValidate></form>

Is there a way to give HTML inputs some sort of namespace to avoid collisions?

<!-- Some place on the webpage -->
<input type="text" id="firstName">
<!-- Some other place on the same webpage, or maybe content ajaxed in later -->
<input type="text" id="firstName">
Let's say I have a server-side script that generates an HTML page with some input fields each with its own ID. One server-side class may be responsible for adding input fields to one part of the webpage while another class handles another part of the webpage. Or you might have different programmers working on different parts of the page. I want to avoid collision with the HTML input field IDs. An example of this could be a parent form that has a jQuery dialog popup with input field IDs the same as the parent. Currently, I am prefixing the IDs with the name of the server-side class that generates them (and an underscore to make it clear which part is the prefix). To get a fully unique ID this way, I might have to start including the full namespace of the server-side class, and this might make my IDs very long.
Is there a better approach than prefixing the inputs or what is the best practice for this? I normally use camelCase for all my variables, with only this exception. Is this a good exception for breaking that rule?
What are most of you doing? Are you altering the way you select these input fields instead of by ID? Wrapping the input fields in form tags or div tags and adding functionality to the server-side to create these? (I'd like to have the freedom of not restricting what I wrap these inputs in to select them. My server-side code should just generate client-side code that grabs the values only knowing those inputs are going onto the page, and not knowing about any other tags on the page. Much easier to manage.) Are you adding css classes to each group of fields?
This answer is a little more directed towards users coming in from search engines. In my opinion, if you are using the id attribute in a dynamically generated form, they should probably be some kind of generated id/hash, unless it truly is a unique field. That aside, this is probably the best way to namespace HTML forms, especially when it is subject to collision:
<input name="pet_store[name]" value="" />
<input name="dogs[0][name]" value="" />
<input name="dogs[1][name]" value="" />
<input name="dogs[2][name]" value="" />
<input name="cats[0][name]" value="" />
<input name="cats[1][name]" value="" />
<input name="cats[2][name]" value="" />
If submitted all at once, the inputs will automatically be organized into arrays (at least in PHP, for nodejs you might have success with https://www.npmjs.com/package/qs).
In jQuery, you can select all dog name fields like this:
$('input[name$="[name]"][name^=dogs]')
I would use classes in this case. If you can't control what the uniqueness of ID's then they become pretty meaningless.
Instead of generating a super-long class name from the code that generates the html, you could add many shorter css classes to inputs that need them. It's not unusual to have lots of different classes in your document and they can all be used together with jQuery selectors. Also remember that if your inputs are in different forms then the form id (or class) could also be considered to work a bit like a 'namespace' too.
For reference, point 7.5.2 of the W3C Global Structure of an HTML document states that the id must be unique.
The idea of ids is that they are a unique reference to an element and as such it is not legal (valid HTML) to have multiple elements referring to the same id. If you want to avoid collisions and still identify the element you could use a combination of classes.
For example if you have 2 forms asking for a name (as in your previous comment) you could use:
<input type="text" class="ajax firstName" />
For the form generated by ajax, and
<input type="text" class="initial-form firstName" />
For the initial form on the webpage.
Equally you could use the data- attribute to hold a namespace. E.g:
<input type="text" data-namespace="ajax" class="firstName" />
(This can be accessed through Javascript with element.dataset["namespace"])
Use data-xxx attributes if you must, but I can't really think of a practical case of independent server-side scripts generating hundreds of DOM elements with unique IDs up to the point where name collision would become an issue.

several class different in one input?, how is it?

how is puting tow class different in one input?
classes is: auto and date.
did is this true?
<input type="text" name="date_go" class="auto" class="date">
Don't do that. A HTML element should contain unique attributes only.
In my experience, browsers tend to just use the first or last one defined in the markup (what does your browser do?)...
Google Chrome has decided to use the first attribute defined in the markup when building the DOM.
Instead, do this...
<input type="text" name="date_go" class="auto date">
...or in other words, if you want multiple classes, join them together with a space in the class attribute.
jsFiddle.