angular2: Why we use asterik with ngif and ngfor? - angular2-template

here is the sample code for the asked question.<p *ngIf="heroes.length >= 4">There are many heroes!</p>
If i remove * it gives me error

source:https://angular.io/docs/ts/latest/guide/structural-directives.html#!#asterisk
The asterisk (*) effect
COPY CODE
<div *ngIf="hero">{{hero}}</div>
<div *ngFor="let hero of heroes">{{hero}}</div>
We're prefixing these directive names with an asterisk (*).
The asterisk is "syntactic sugar". It simplifies ngIf and ngFor for both the writer and the reader. Under the hood, Angular replaces the asterisk version with a more verbose form.
The next two ngIf examples are effectively the same and we may write in either style:
COPY CODE
<!-- Examples (A) and (B) are the same -->
<!-- (A) *ngIf paragraph -->
<p *ngIf="condition">
Our heroes are true!
</p>
<!-- (B) [ngIf] with template -->
<template [ngIf]="condition">
<p>
Our heroes are true!
</p>
</template>
Most of us would rather write in style (A).
It's worth knowing that Angular expands style (A) into style (B). It moves the paragraph and its contents inside a tag. It moves the directive up to the tag where it becomes a property binding, surrounded in square brackets. The boolean value of the host component's condition property determines whether the templated content is displayed or not.

The reason we use asterik for ngIf and ngFor directive is because, they change the structure of the DOM. and they are also called as structural directives. Every structural directive prefix with asterik.
Examples of Structural directives: *ngIf, *ngFor, *ngSwitchCase, *ngSwitchDefault etc are some examples of structural directives
Code Example:
<p *ngIf="true"> Expression is true and ngIf is true. This paragraph is in the DOM. </p>
<p *ngIf="false"> Expression is false and ngIf is false. This paragraph is not in the DOM.</p>
checkout this link to dive deep in structural directives:
https://angular.io/guide/structural-directives

Related

How to use `v-if` and `v-for` on the same element?

Hi I'm trying to figure out how to use v-if on a iterated element which also uses v-for. I need to check if the current element has any of a series of classes, which are numbers.
so the classes of each article would be:
<article class="post-item post-guide 12 22 19 30 55">...
this is the HTML that renders all:
<article v-if="showIfHasClass" :class="'post-item post-guide ' + guide.categories.toString().replace(/,/g, ' ')"
v-for="(guide, index) in guides" :key="index">
<header>
<h1 class="post-title">
{{ guide.title.rendered}}
</h1>
</header>
</article>
I have tried with methods that check the class of all elements, that works, but i'm trying to use a clean Vue built-in solution with v-if without success, i'm not able to retrieve the class of this in a successful way.
Should showIfHasClass be a computed property? I have tried with that too... but it seems, I'm missing something along the way.
my data I have to check against is an array:
data:{
guides: [...]
selectedCategories: [1, 22, 33, 100, 30];
}
or maybe it is better to directly loop over the guides and check if they have the selectedCategory or not, then remove the element from the guides data array?
What is more effective?
Besides the option to create an additional filtered computed (effectively eliminating the need to use v-for and v-if on the same element), you also have a template level way of dealing with such edge-cases: the <template> tag.
The <template> tag allows you to use arbitrary template logic without actually rendering an extra element. Just remember that, because it doesn't render any element, you have to place the keys from the v-for on the actual elements, like this:
<template v-for="(guide, index) in guides">
<article v-if="isGuideVisible(guide)"
:key="index"
class="post-item post-guide"
:class="[guide.categories.toString().replace(/,/g, ' ')]">
<header>
<h1 v-text="guide.title.rendered" />
</header>
</article>
</template>
isGuideVisible should be a method returning whether the item is rendered, so you don't have to write that logic inside your markup. One advantage of this method is that you can follow your v-if element with a fallback v-else element, should you want to replace the missing items with fallback content. Just remember to also :key="index" the fallback element as well.
Apart from the above use-case, <template> tags come in handy when rendering additional wrapper elements is not an option (would result in invalid HTML markup) (i.e: table > tr > td relations or ol/ul > li relations).
It's mentioned here as "invisible wrapper", but it doesn't have a dedicated section in the docs.
Side note: since you haven't actually shown what's inside guide.categories, I can't advise on it, but there's probably a cleaner way to deal with it than .toString().replace(). If guide.categories is an array of strings, you could simply go: :class="guide.categories".
I think the most Vue way is to create a computed property with filtered items from selected categories, then use that in v-for loop (the idea is to move the business logic away from template).
computed: {
filteredItems(){
return this.guides.filter(e => this.selectedCategories.includes(e.category))
}
}
Also, as a note, it is not recommended to use v-if and v-for on the same element, as it may interfere with the rendering and ordering of loop elements. If you don't want to add another level of nesting, you can loop on a 'template' element.
<template v-for="item in items">
// Note the key is defined on real element, and not on template
<item-element v-if='condition' :key="item.key"></item-element>
</template>

Data-Filter Overriding Data-Search Attribute

Using DataTables, I am witnessing a reproduceable issue where the value of the data-filter html attribute is overriding the searchability of the data-search html attribute.
<td data-search="Jared Next" data-order="Jared Next" data-filter="Full-Time DM">
<div class="mb-2">
Jared Next
</div>
<div class="mb-2 text-muted small" title="Number of total deals posted by DM">
Posted: 294
</div>
</td>
When searching by "jared" the row does not appear.
When searching by "full-time dm" the row does appear.
Worth mentioning that the filter works as expected:
I apologize if I've not provided enough code to re-create the issue or if DataTables experts want the whole table.
I can easily provide it all.
The data-search and data-filter attributes are synonyms, in DataTables.
See here for details.
You should use one or the other, but not both at the same time.
Also, from the same doc link as above, in case it is relevant: Make sure the attributes are used consistently for every cell in a column:
In order for the HTML 5 data-* attribute detection and processing to work correctly, all cells in a column must have the same attribute available.

Get attributes of a empty child node

I want to transform a old HTML4 code to have closed tags in order to achieve compatibility with WCAG.
I have a lot of anchors without content, used as internal links, like
<h3> <a id="julio" name="julio"></a>Julio 2015</h3>
For reasons I do not understand, some browsers do not understand the self-enclosed tag, and interpret it as the start of an anchor (without end).
<h3> <a id="julio" name="julio"/a>Julio 2015</h3>
Then, I want to delete empty anchors and move the attributes to the parent tag:
<h3 id="julio" name="julio">Julio 2015</h3>
The tool I have to use only supports XSLT 1.0
How can I get it?

How to build an Angular directive that doesn't generate containing tags?

I'm having a little difficulty with this, I'm hoping maybe someone has some ideas. It's a very complex situation, but I'll try to simplify and nutshell it here.
Let's say that I have a directive that generates several elements, for example, a Label and a Textbox. This directive will need to generate different content in differtag ent scenarious.
The problem with a directive that has more than one element in it is that you can't use the "replace:true" tag unless you wrap everything in one element. "replace" doesn't like multiple root elements. If you don't use the "replace" option then the tag that generates the directive becomes the containing element.
I don't want all these extra tags. It's breaking my CSS and generating unnecessary content. So instead of this:
<div ng-repeat="s in something">
<my-directive>
<label><input>
</my-directive>
<my-directive>
<label><input>
</my-directive>
<my-directive>
<label><input>
</my-directive>
</div><!-- End repeat -->
I want this:
<div ng-repeat="s in something">
<label><input>
<label><input>
<label><input>
</div><!-- End repeat -->
I hope this question makes sense.

In Bootstrap 3, is it possible to use col-*-* classes on definition terms with horizontal definition lists?

For the following markup:
<dl class="dl-horizontal">
<dt>A few words describing the term</dt>
<dd>The data associated with the term</dd>
</dl>
The dt term element is fixed width (at 180px) and cannot be changed with col- due to specificity of CSS. For example, the below does not work:
<dl class="dl-horizontal">
<dt class="col-sm-3">A few words describing the term</dt>
<dd class="col-sm-9">The data associated with the term</dd>
</dl>
Description lists are for name-value pairs and a fixed width is not suitable for some languages where the single word term is longer than 180px. Truncating is not possible (it truncates valuable meaning) and word-wrapping (using Stack Overflow overrides) is not readable.
Do I need to add extra classes or should I chase up with Twitter Bootstrap?
Edit
Given the lack of answers, I have opened an issue with bootstrap:
https://github.com/twbs/bootstrap/issues/14983
...you can always write overwrite code for the col-sm-3 and col-sm-9 classes (following the exact example), but I guess it would be easier to write your own classes using media queries and the same breakpoints you are using in your bootstrap file. You can also use this custom class to set a new minimum width.
#media (min-width:XXX) and (max-width:XXX) {
dt.col-sm-3 {
width:25%;
}
dt.col-sm-9 {
width:75%;
}
}