I need to create some automated testing tags for an angular web application. Basically, I intend to create a bunch of html ids for the components of interest in my unit test. What would be best practice for this activity? Does the angular template syntax <html-tag #variable ... work in the same way as <html-tag id="variable" ... ?
#variable is used for creating template reference variable - and will not be available at run time when HTML is rendered. You are better off using id="variable" to identify HTML elements in your tests.
The <html-tag #variable pick up the reference to HtmlElement or superior. It can be marked on the property exportAs
The <html-tag id="variable" attribute represents the element's identifier, reflecting the id global attribute
Related
Does anyone know why you can use [id] and you must use [attr.contenteditable] as property binding in Angular?
I have researched for some time and I can't find an answer.
Why some html native attributes can be modified just with its name while others need to be modified through the attr property?
(This answer assumes you're binding to a HTMLElement rather than an in-app model object. Given the [attr.{name}]-syntax is only supported for DOM HTMLElement objects this assumption should stand)
When working with the DOM, the DOM interfaces for certain elements define first-class/native properties (as in JavaScript properties) for certain HTML attributes.
For example, the HTMLElement DOM interface defines a first-class property id, which is why you can directly use it in a binding expression: [id]. Similarly the HTMLAnchorElement exposes the href property.
(I note that contenteditable is a a defined DOM interface property in WHATWG HTML LS, but not the W3C's DOM specs, interesting...)
However, arbitrary (ultra-modern, user-defined, and obsolete) HTML attributes are not exposed through DOM interfaces and so can can only be accessed via the attributes collection in the DOM. Angular requires you to use [attr.{name}] for non-DOM-property attributes so that it knows it has to use the attributes collection instead of assuming it can bind directly to a DOM property.
To answer your question more directly:
when use [name] vs [attr.name]?
Follow this flow-chart:
Is the value I'm after exposed as a DOM interface property?
Yes:
Use [propertyName]
No:
Is the value I'm after a HTML attribute without a corresponding DOM interface property?
Yes: Use [attr.{attributeName}]
No: Quit your job and let someone else deal with the emotional and mental stresses of the fast-moving JavaScript developer ecosystem.
From the docs
Though the target name is usually the name of a property, there is an automatic attribute-to-property mapping in Angular for several common attributes. These include class/className, innerHtml/innerHTML, and tabindex/tabIndex.
So not all attributes are mapped within Angular.
Using the attr. prefix will literally emit the suffix as a string attribute.
Take this example:
<div [attr.data-my-attr]="value"></div>
Will produce the following HTML, assuming that the component property value has a value of 5:
<div data-my-attr="5">
</div>
Why you must use [attr.contenteditable]="editable"?
This isn't true. This is one way of emitting the contenteditable="true" attribute. Another is to use the Angular attribute [contentEditable]="editable", assuming some component property editable exists.
<div [contentEditable]="editable"></div>
DEMO: https://stackblitz.com/edit/angular-ujd5cf
The reason is because most common HTML attributes have special #Input properties in angular itself. E.g. id class etc, but there are way too many attributes to have this for each of them, so those more specific require you to use attr. syntax. The same thing happens with shorthand binding e.g. [style.width.px], you cannot do this with every single property. Event bindings have similar behavior. E.g. you can say (keyup.enter) but not (keyup.j). Angular tries to make your life easier when it can with most common things, but it also provides option to do other things as well.
This also means that you can do e.g. [attr.id]=
To set string #Input() properties of the component, we can use two type of syntax:
<my-component caption="Hello there" type="primary" someThing="text value"></my-component>
OR:
<my-component [caption]="'Hello there'" [type]="'primary'" [someThing]="'text value'"></my-component>
I'm fully aware of the differences between those two types of bindings. The question is: If I have bunch of string #Input() properties that I want to set statically, can I use simple attribute binding syntax (first example) than more "meaty" property binding syntax (second example)?
What is the recommendation, and why? I.e. what are the trade-offs and is it preferable to use property-binding always, even for setting static string inputs?
Here are the few drawbacks I can think of:
Attribute bindings are actually applied as HTML attributes, and e.g.
user can see/alter them via browser's dev tools easily. Property
bindings are not part of the markup.
Attribute bindings might collide
with actual HTML attribute names (unless you prefix them with data-
which defeats the whole purpose of simplicity). Actual example that
already bit me is title attribute.
There is no intellisense in markup for attribute bindings with Angular Language Service.
But the major advantage is the simplicity. In the example above, you would agree that the first form is more elegant. In my projects it seems that big number of properties are constant (one-time-set) string properties, and the syntax makes actual difference in readability.
So... Is it a bad practice to use attribute-binding syntax for custom (non-HTML) string properties? (Given the fact that I'm aware/ok with above listed few limitations)
These are a couple of things I like to add:
Attributes are just plain static fields.
There is a fine line when attributes become properties.
Simplicity is not the goal here, modularity and reuse-ability is.
Property binding give you more control in your component and you can use a component in any like any data-driven or static scenario.
One component build right with property binding can be used in 20 different projects.
But if you got no such requirement then you can use attributes. They are fine.
I will not say which one is better, both have their use cases but overall property bindings are lot more powerful and flexible.
And last thing I like to mention for all readers:
In front-end development any one can modify the code. We use
validations just to provide a smooth user experience. Other than that
any one can get the code or alter HTML if they want to, that's why we
use server side validations. Angular pipe line is complex but
hack-able. A user can wrap a JSON object and send it to server
bypassing all our validations. So for all readers who are new front-end
devs, we don't bother too much about security, we try our best to give
a good user experience.
I have a doubt about good practices writing HTML with Javascript.
I've came up with an idea (probably not the first, but couldn't find a clear reference about that) to mark some elements as candidates to load some data when it's available (after some user interaction). Let me exemplify:
Suppose I have a request that returns the following:
GET /animals/dog
{
name: "Gutemberg",
race: "doberman",
age: "2y"
}
The code I wrote binds fields in the response to elements that are candidates to load such value.
For example: With the request above, I could use the following tags:
<input name="dog-name-field" data-load-dog-name type="text"/>
<input name="dog-age-hid" data-load-dog-age type="hidden"/>
Each tag would receive the property value because it's marked as a candidate to do so - dog-name-field will have a value of "Gutemberg" when everything executes . That will happen everytime the request is reloaded. For now, I just get the data type I've searched ("dog"), concat it with the property "name/age" to form the attribute data-load-type-property and set a value to everyone that has such attribute.
I have a feeling that attributes are not meant to be used just like that, but I'm not aware of any real downsides to that. As I could not find it for the lack of a clear name to this approach, I'd like some guidance.
Is there a name for such technique? Is it a bad practice? If so, why?
PS:
To comply with SO good practices, I'd like the answers to be reference-guided and not based solely on opinion whenever possible. If no reference is provided, please, let us have a solid, well described example.
I have a feeling that attributes are not meant to be used just like that
Let's see what custom data attributes are meant to be used for:
Custom data attributes are intended to store custom data private to
the page or application, for which there are no more appropriate
attributes or elements. These attributes are not intended for use by
software that is independent of the site that uses the attributes.
(from w3.org)
So whether using data-attributes is "appropriate" in your case depends on your needs: if the DOM API doesn't provide better attributes to do that then it's appropriate.
If your need is just to select some element to change the textContent then you have two more appropriate/simpler options:
1) Using the id attribute if your elements are going to be unique in the document
The id global attribute defines a unique identifier (ID) which must be
unique in the whole document. Its purpose is to identify the element
when linking (using a fragment identifier), scripting, or styling
(with CSS).
(from id on MDN)
2) Using the class attribute if your elements are going to be used in multiple instances in the document
The class global attribute is a space-separated list of the classes of
the element. Classes allows CSS and Javascript to select and access
specific elements via the class selectors or functions like the DOM
method document.getElementsByClassName.
(from class on MDN)
As #Supr says in his answer, what you are doing is a very simple implementation of data-binding. data-binding can involve a lot more complexity than what you are doing at the moment; for example you may want to:
keep in sync your UI with a Javascript object which represent your business model instead of directly injecting data coming from an Ajax call,
update other attributes (value, style) and not only innerHTML or textContent,
have your business model updated in reaction to changes on the UI (two way data binding)
To implement all these features, simple id and class selectors are not sufficient, and this is why frameworks which implement data-binding, like KnockoutJS or AngularJS, use the more flexible data-* attributes instead (AngularJS is actually using its own ng-* attributes, but allows to use the alternative data-ng-* syntax for using HTML validation tools).
Data attributes allow to describe much more complex bindings:
<input data-bind="visible: editing, value: name, hasFocus: editing" />
Check KnockoutJS documentation for the meaning of the above code, it is not relevant to this example but just imagine describing that with classes or ids, it wouldn't be very convenient.
TL;DR
If you don't plan to implement more complex features you might want to use class and id instead.
This is called binding. Sometimes data binding and sometimes template binding.
Various frameworks provide mechanisms for this, though the syntax varies.
AngularJS example:
<input ng-model="dog.name" />
Knockout example:
<input data-bind="textInput: dog.name" />
React example:
<input value={this.state.dog.name} />
These are all quite popular frameworks/libraries, so I think it's safe to say it is not considered bad practice. The main difference from your approach is that they use the value of the attribute to specify the reference into the model (i.e. the "dog.name" part of your attributes), while you are putting the reference in the attribute name. In practice this is mostly a matter of style. Separating the reference from the "marker" (i.e. "data-load") is perhaps a bit more readable.
my question concerns about Rails + HAML
I would like to conditionally set a class atribute to a HTML tag. I figured out that the best way to do this is by setting controller variables that are used to set a class of the appropriate HTML tag.
The only solutions I found googling tell me to use a conditional in HAML. But I don't think this is the best approach, since Views shouldn't have any logic control.
So, how could I do this directly from the controller? Which are those controller variables that can set a class of a html tag?
Haml indeed discourages using logic in views and makes it easy to create helpers instead. So one solution would be to create your helper method with any logic inside.
You can't control html markup from controllers, the views are for this purpose.
If you don't want to create a separate helper (it's too much for your requirements), use existing tag helper that comes with rails. It accepts a hash of options which can be intialized from your controller if you like.
But again, I'd go for helper.
For simple logic (like setting a class) you can use haml_tag that exposes class attribute value as a string:
- haml_tag :th, class: "#{'hilite' if params[:order_by]=='title'}" do
- haml_concat link_to 'Movie Title', movies_path(order_by: 'title')
This way you still have conditional logic in the view but resorting to helper in this case may be an overkill.
If you don't want logic in your haml templates then you should move it into a helper. There's really no way for a controller to set the class for a specific html tag; that's not what controllers are for.
If I write
<form wicket:id="form" id="form>
or even
<form wicket:id="form>...
Then the rendered HTML shows the id 'form' appended with different numbers whenever the page is refreshed e.g.
<form id="form7"....
Is there a way to disable this behavior of the Wicket framework?
We set markup ids by hand extensively on our project to ease automatic testing with Selenium testing framework. It definitely works.
Component.setOutputMarkupId(true); // write id attribute of element to html
Component.setMarkupId("someid"); // id attribute of element is "someid"
This is the behavior you want in most cases when using wicket. The dynamic id is meant to prevent id collisions when Ajax behaviors are added to components or added to ajax responses for refreshing. For any of these situations, you really need both the client response and the server side state to be in cahoots. If there are external js resources you need the id of a component for dom lookup, then I would suggest adding a custom wicket component behavior that would then generate the js call to a function passing in the generated id.
I realize what I'm going to describe leads you more into the forest of Wicket. But I have been more than happy with the ajaxy stuff that Wicket opens up for you out of the box.
This is Wicket desing feature. You can use class for linking styles and components.
<form wicket:id="form" id="form>
Also you can to try (I never did it) setMarkupId . I'm not sure that it good way.
It has been a while since I worked with Wicket, but I remember that when wicket uses ajax elements, its ids are auto-generated (the id of the tag, not the wicket:id). You can control the id of the tag when not using and ajax element. In your case, since there is no code, I would guess that you will have to change any AjaxButton or Ajax* from your form.
Yes you can write custom JavaScript... you just need to implement it according to the 'Wicket way'. You can decorate components, Ajax calls etc. with custom JavaScript, then it all plays nicely.