Conditional bind property fxFlex in Angular 9 - javascript

I am using the Angular flexlayout which works perfectly, I am trying to bind fxFlex to the child element like below
<div [fxLayout]="fields.layoutConfig.fxLayout + ' wrap'" fxLayoutGap="10px">
<div *ngFor="let field of fields.componentConfig;" [fxFlex]="field?.componentProperty?.fxFlexChildLayout?.fxFlex">
<ng-container reactiveField [field]="field" [group]="form"></ng-container>
</div>
</div>
Whenever the field?.componentProperty?.fxFlexChildLayout?.fxFlex is null or undefined it should not bind fxFlex to the div
I have tried
[fxFlex]="field?.componentProperty?.fxFlexChildLayout?.fxFlex != undefined ? field?.componentProperty?.fxFlexChildLayout?.fxFlex : 'null'"
[attr.fxFlex]="field?.componentProperty?.fxFlexChildLayout?.fxFlex" --> this does nothing it doesn't bind `fxFlex` when it has value as well
But still in the DOM I can see it add the style as
style="flex: 1 1 100%; box-sizing: border-box;"
I don't want to add style if the value of field?.componentProperty?.fxFlexChildLayout?.fxFlex is undefined or null
How can I achieve this ?

You cannot conditionally apply a directive is the issue. You can dynamically set the value of a directive input which is what you are doing above, but all divs will have the fxFlex directive.
So:
<div [fxLayout]="fields.layoutConfig.fxLayout + ' wrap'" fxLayoutGap="10px">
<ng-container *ngIf="field?.componentProperty?.fxFlexChildLayout?.fxFlex; else noFxFlex">
<div *ngFor="let field of fields.componentConfig;" [fxFlex]="field?.componentProperty?.fxFlexChildLayout?.fxFlex">
<ng-container reactiveField [field]="field" [group]="form"></ng-container>
</div>
</ng-container>
<ng-template #noFxFlex>
<div *ngFor="let field of fields.componentConfig;">
<ng-container reactiveField [field]="field" [group]="form"></ng-container>
</div>
</ng-template>
</div>

This isn't the answer you asked for, but as #Randy stated in their answer because you can't conditionally apply a directive, an alternative solution would be to pass "none" to the [fxFlex] directive.
"None" should size the child element according to its width and height properties. It is fully inflexible. It neither shrinks nor grows in relation to the flex container.
That should have the same effect as removing the [fxFlex] directive, however, the DOM element will still have some flex styles on it.
<div [fxLayout]="fields.layoutConfig.fxLayout + ' wrap'" fxLayoutGap="10px">
<div *ngFor="let field of fields.componentConfig;" [fxFlex]="field?.componentProperty?.fxFlexChildLayout?.fxFlex || 'none'">
<ng-container reactiveField [field]="field" [group]="form"></ng-container>
</div>
</div>
See https://github.com/angular/flex-layout/wiki/fxFlex-API#fxflex-options

You just need to declare a variable in your TS and assign
HTML
<div fxFlex="{{fxflexwidth}}">
TS
fxflexwidth: number = 50;
in your function just return when you need to change the attribute:
this.fxflexwidth = 100;

Related

Vue template with v-if condition does not react on value change

I have a template with v-if condition base on the data value. But if I change the value it does not redrav the template. I see the value ich changed in Vue debugger but v-if blocks it like it was empty like on component load.
Here is the code:
<div v-if="newSelectedDevices" class="mt-2 mb-2">
<template>
<b-field class="has-horizontal-line pb-2">
<b-taglist>
<b-tag v-for="(included, index) in newSelectedDevices"
:key="'included_' + index"
// This is the problem. It set is-hidden although isNew value is true
:class="{'is-hidden': included.isNew, 'taglist': true, 'is-danger': true}"
closable
#close="removeFromNewSelected(index)"
>
{{ included.name }}
</b-tag>
</b-taglist>
</b-field>
</template>
</div>
What is wrong with this code? Thanks for any help.

How to loop through unknow number of nested json object in Angular with ngFor?

I'm trying to display all the reply from this json :
https://www.reddit.com/r/AskReddit/comments/k8w43d/people_with_the_last_name_pepper_who_have.json
So, depending of the post im loading and the reply, my number of children will differ. How can I loop throught it until I reach the last reply with children (body[2].data.children) ?
Like this :
<div class="replies-box" *ngFor="let reply of comments.body[1].data.children">
<div class="reply-header">
<p class="reply-author"><b>From</b> : {{ reply.data.author }}</p>
<p class="reply-send"><b>Send</b> : {{ this.getDateReply(reply.data.created_utc) }}</p>
</div>
<div class="text-first-reply" [innerHTML]="this.getHtmlDecode(reply.data.body_html)">
</div>
</div>
I have only the first level of reply, is there a way to simply loop through them all ?
Thanks in advance.
I would use a recursion type of approach.
Develop a app-comment component and if comment has children, loop over the children and display the app-comment. That way it will loop over the comments until no more children
<div *ngIf='comment'>
<span *ngIf='comment.kind; else showComment'>Kind: {{ comment.kind }}</span>
<ng-template #showComment>
<span>{{ comment }}</span>
</ng-template>
<div>
<app-comment *ngFor='let child of comment.data?.children' [comment]='child'> </app-comment>
</div>
</div>
See this sample illustration
Simply use ngFor inside ngFor with help of ng-container (will not create extra dom elements)
<div class="replies-box">
<ng-container *ngFor="let commentBody of comments.body">
<ng-container *ngFor="let reply of commentBody.data.children">
<div class="reply-header">
<p class="reply-author">
<b>From</b> : {{ reply.data.author }}
</p>
<p class="reply-send">
<b>Send</b> : {{ this.getDateReply(reply.data.created_utc) }}
</p>
</div>
<div class="text-first-reply" [innerHTML]="this.getHtmlDecode(reply.data.body_html)">
</div>
</ng-container>
</ng-container>
</div>

Cannot read property 'setProperty' of undefined fxFlex issue with ng-container Angular 9 Flex Layout

<div [fxLayout]="fields.layoutConfig.layoutDirection + ' wrap'" fxLayout.xs="column"
[fxLayoutGap]="fields.layoutConfig.fxLayoutGap">
<ng-container [fxFlex]="50" *ngFor="let field of fields.componentConfig;" reactiveField [field]="field" [group]="form">
</ng-container>
</div>
Trying to use the [fxFlex]="50" inside the container getting an error Cannot read property 'setProperty' of undefined
Some of the issues https://github.com/angular/flex-layout/issues/1046
https://github.com/angular/flex-layout/issues/381
you shouldn't use property binding for fxLayout and fxLayoutGap.
I had the same issue with
<ng-container fxLayout="row" fxLayoutAlign="right">
by changing <ng-container> into a <div> the error was gone...
Bind the container inside the <div>
<div [fxLayout]="fields.layoutConfig.fxLayout + ' wrap'" fxLayout.xs="column"
[fxLayoutGap]="fields.layoutConfig.fxLayoutGap"
[fxLayoutAlign]="fields.layoutConfig.fxLayoutAlignHorizontal + ' ' + fields.layoutConfig.fxLayoutAlignVertical">
<div [fxFlex]="fields.layoutConfig.fxFlex" *ngFor="let field of fields.componentConfig;">
<ng-container reactiveField [field]="field" [group]="form"></ng-container>
</div>
</div>

How to know if there are child divs hidden by overflow: hidden in Angular6

Here is the problem I want to solve.
<div class="row" style="overflow:hidden;">
<app-car
*ngFor="let car of cars; trackBy: trackByFunction"
[car]="car"
>
</app-car>
</div>
<button> More <button>
I want to show the more button if there are cars hidden by the overflow:hidden property of the parent.
jquery;
$("div").each(function() {
if($(this).parent().css('overflow') == 'hidden'){
console.log("there is an overflow hidden");
}
});
You can use viewChild and ngIf in angular6 to achieve your situation
<div class="row" style="overflow:auto;height:50px" #container>
<app-car
*ngFor="let car of cars; trackBy: trackByFunction"
[car]="car">
</app-car>
</div>
<button *ngIf="container.style.overflow === 'hidden'"> More <button>
and include below item in your ts file
#ViewChild('container') private container: ElementRef;

How to disable NgbTooltip if tooltip template is empty, in Angular2?

I'm showing an array of data inside a tooltip, so I used a template. My code looks like:
<ng-template #ToolTipTemplate>
<small *ngFor="let month of data.months; let first = first; let last = last"> {{ month.appliedMonthYear | utc | date:'MM/y' }}{{ last ? '' : ', ' }} </small>
</ng-template>
<span [ngbTooltip]="ToolTipTemplate">Months: {{data.months.length}}</span>
If data.months is empty I do not want the tooltip to appear. Currently if it's empty it shows the tooltip arrow only.
I've tried adding an *ngIf on the <small> tag inside the template, but that didn't work. I've also tried adding *ngIf into <ng-template> to no avail.
Ok, I was finally able to figure it out. Here's what I had to do
<span [ngbTooltip]="(data.months?.length) ? ToolTipTemplate : ''">Months: {{data.months.length}}</span>
You can take the element reference like #t="ngbTooltip" and then manually fire the tooltip. In your case fire it if required or don't show the tooltip at all.
<div
[ngbTooltip]="(data.months?.length) ? ToolTipTemplate : ''"
triggers="manual"
#t="ngbTooltip"
(mouseenter)="(data.months?.length) && t.open()"
(mouseleave)="t.close()">
show Tooltip
</div>
You can disable it with
<span [ngbTooltip]="ToolTipTemplate" [disableTooltip]="true">Months: {{data.months.length}}</span>
See docs for more info: https://ng-bootstrap.github.io/#/components/tooltip/api
Simple way of doing is
<div *ngIf='data.months.length > 0'>
<ng-template #ToolTipTemplate>
<small *ngFor="let month of data.months; let first = first; let last = last"> {{ month.appliedMonthYear | utc | date:'MM/y' }}{{ last ? '' : ', ' }} </small>
</ng-template>
<span [ngbTooltip]="ToolTipTemplate">Show Info</span>
</div>
<div *ngIf='data.months.length === 0'>
<span>Show Info</span>
</div>
You can use disableTooltip input attribute.
https://ng-bootstrap.github.io/#/components/tooltip/api

Categories

Resources