To insert dynamic elements with specific style attributes in *ngfor(Angular) - javascript

I have implemented drag and drop feature referring to a youtube tutorial
I have *ngFor which will generate divs from existing roomsFloorZone array, now my objective is to generate divs using style attribute and value received from backend response provided to the same *ngFor, as all the divs from existing roomsFloorZone or from backend response needs to be under same parent div
I have tried with already existing elements present in roomsFloorZone
import {Component, OnInit, AfterViewInit, Input, SimpleChange,
SimpleChanges} from '#angular/core';
#Component({
selector: 'floor-zone',
templateUrl: './floorzone.component.html',
styleUrls: ['./floorzone.component.scss']
})
export class FloorZoneComponent{
urlFloorZoneIn: any;
roomsFloorZoneIn: any;
#Input() urlFloorZone;
#Input() roomsFloorZone;
#Input() currentBoxFloorZone;
ngOnChanges(changes: SimpleChanges) {
if (changes.urlFloorZone && changes.urlFloorZone.currentValue) {
this.urlFloorZoneIn = changes.urlFloorZone.currentValue;
}
if (changes.roomsFloorZone && changes.roomsFloorZone.currentValue) {
this.roomsFloorZoneIn = changes.roomsFloorZone.currentValue
}
}
dropzone1 = [];
currentBox?: string = this.currentBoxFloorZone;
move(box: string, toList: string[]): void {
box = this.currentBoxFloorZone;
this.removeBox(box, this.roomsFloorZoneIn);
this.removeBox(box, this.dropzone1);
toList.push(box);
}
removeBox(item: string, list) {
if (list.indexOf(item) !== -1) {
list.splice(list.indexOf(item), 1);
}
}
}
I have an array existing roomsFloorZoneIn , from which I drag and drop the elements in the below html and the *ngfor works for that
html
<div id="toget" class="dropzone" [ngStyle]="{'width':'100%','background-
image': 'url('+urlFloorZoneIn+')','background-repeat': 'no-repeat',
'background-position': 'center', 'background-size': '100% 100%',
'border':'1px solid black', 'height':'340px'}" appMovableArea
appDropzone (drop)="move(currentBox, dropzone1)">
<div class="box" *ngFor="let box of dropzone1" appDroppable
(dragStart)="currentBox = box" appMovable>
{{ box.dis }}
</div>
</div>
My objective is to provide style(transform attribute) and (abc or def) for {{box.dis}} taken from below snippet
[I have style and node values handy]
to *ngFor for placing the divs
`<div xmlns="http://www.w3.org/1999/xhtml">
<!--bindings={
"ng-reflect-ng-for-of": ""
}-->
<div _ngcontent-c5="" appdroppable="" appmovable=""
class="box draggable movable ng-star-inserted" touch-action="none"
style="transform: translateX(183.2%) translateY(56%);"> abc
<span _ngcontent-c5="">X</span>
</div>
<div _ngcontent-c5="" appdroppable="" appmovable=""
class="box draggable movable ng-star-inserted" touch-action="none"
style="transform: translateX(183.2%) translateY(56%);"> def
<span _ngcontent-c5="">X</span>
</div>
</div>`
So this *ngFor for should work for existing elements(roomsFloorZoneIn) as well as I should be able to insert some elements received from backend(using their style attribute and node value)
Note: I already have the style and node value handy

If the two lists can come one after the other, you can use two separate <div>'s, both with *ngFor's using the two Arrays:
<div class="myEnclosingDiv">
<div class="firstList" *ngFor="let element of firstArray">
{{ element.stuff }}
</div>
<div class="secondList" *ngFor="let element of secondArray">
{{ element.otherStuff }}
</div>
</div>
On the other hand, if the two lists need to be mixed somehow, you simply create a new Array in your TypeScript code and use a single *ngFor.

Related

How to work with variables from a loop in HTML and with a component property?

The data I work with (bosses[]) has a boss object with contains the key-value email which is an string. I want to create the anchor with that string in the HTML. Also note that there's a loop in HTML that allows to access to each boss in bosses[].
So how can I access to create an anchor with boss.email which it only exists in the HTML loop?
I've tried <a [href]=`"mailto: + boss.email"></a> but doesn't work.
the html:
<div class="boss" *ngFor="let boss of bosses" >
<div class="boss-text">
<div class="boss-text-name">{{boss.name}} </div>
<div>{{boss.email}}</div>
<a [href]="mailto: + boss.email"></a>
</div>
</div>
The component:
import { Component, Input, OnInit } from '#angular/core';
import { boss} from 'interfaces'
#Component({
templateUrl: 'boss-cell.component.html',
selector: 'boss-cell',
})
export class BossCellComponent implements OnInit {
constructor() {}
bosses: any[] = [{
email: 'kennedy#gmail.com',
name: 'kennedy',
}]
}
You're close! I think this is what you're looking for:
<div class="boss" *ngFor="let boss of bosses" >
<div class="boss-text">
<div class="boss-text-name">{{boss.name}} </div>
<a [href]="'mailto:' + boss.email">{{ boss.email }}</a>
</div>
</div>
You can use interpolation as Suraj already mentionned in the comments, or bind to a function creating the string. Depending on weather you are going to link other elements to the mail, you should pick the cleanest option for you.
Template
<div class="boss" *ngFor="let boss of bosses; let i = index">
<div class="boss-text">
<div class="boss-text-name">{{ boss.name }}</div>
<a [href]="getMail(i)">{{ boss.email }}</a>
</div>
</div>
Script
bosses: any[] = [{
email: 'kennedy#gmail.com',
name: 'kennedy',
}]
getMail(index: number) {
return 'mailto:' + this.bosses[index].email
}
You need to update this line
<a [href]="'mailto:' + boss.email">{{ boss.email }}</a>

Angular - bind InnerHTML with translate in TS file

I have a problem with binding into property to get html and translate it.
I have an innerHTML that I am trying to map to translate.
The problem is it is not translating and displaying the key as it is. P
Below is my code :-
let popupContainer = document.createElement('div');
popupContainer.innerHTML = require('html-loader!../html/myPopup.html').default;
popupContainer.addEventListener('click', clickEventHandler);
document.body.appendChild(popupContainer);
It does not translate and displays as below :- {{'fileverse-name-label' | translate}}
HTML :-
<div class="book__filters">
<hr />
<form class="my____form flex-row" id="filterForm">
<div class="me-3 col-md-3 checker__filters--field">
<label for="fileName" class="band__form--label">{{'fileverse-name-label' | translate}}</label>
<input
type="text"
class="drese__form--input colrs__filters--input"
placeholder="Search for a file verse"
name="fileverse"
id="fileverse"
/>
</div>
<div class="me-3 col-md-3 runner__filters--field">
<label for="chapterLabel" class="chapter__form--label">{{'chapter-label' | translate}}</label>
<select
class="chapter__form--input geeze__filters--input"
name="chapterLabel"
id="chapterLabel"
></select>
</div>
</form>
<hr />
</div>
So, adding html inside a div like you're doing will "just" add your html file into it, without any further logic.
But the pipe needs to be compiled, so you would need to do the following to make this work.
I'll just write step here, please let me know if I should provide more information
With *ngIf
Create a component out of the html you gave (module, component.ts, component.html)
Importing this component whoever you needs it.
Show/Hide it with an *ngIf.
With ViewContainerRef
Create a component out of the html you gave (module, component.ts, component.html)
// component.ts
#Component({
selector: 'foo-bar',
templateUrl: '../foo-bar.component.html', // File where you've added the html
})
export class fooBarComponent {
// ...
}
// module.ts
#NgModule({
declarations: [fooBarComponent],
imports: [
CommonModule,
TranslateModule.forChild()
],
exports: [fooBarComponent],
})
export class fooBarModule {}
Add id to where you need it
<ng-template #loaderContainer></ng-template>
get this element through the where-you-use-it.component.ts file.
#ViewChild('loaderContainer', { read: ViewContainerRef, static: true })
loaderContainer: ViewContainerRef
Add the wished element to it with the ViewContainerRef createComponent() method
this.loaderContainer.createComponent(fooBarComponent)
// This will be at the same place where you initially intended to add the div
Do not forget to add the fooBarModule inside the where-you-use-it.module.ts
Additional
If you're trying to create an "orverlay"
Then I would go with the *ngIf solution and add it into your app.component.html file, just after the <router-outlet> tag

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;

Angular 4 is not rendering my ID in my child component

I have 3 components, they are nested.
But the ID on the last child is not rendering using id = {{myId}}.
I tried [id]=myID as well.
Something like this:
GrandFather:
<app-middle-section #middleSection
myTitle="Title"
myID="my_id_creation" >
</app-middle-section>
Father:
<div class="section rounded">
<div class="title">{{myTitle}}</div>
<app-list #glist
myID= {{myID}}
</app-list>
</div>
Child
<div class="">
<div id="{{myID}}" class=""></div>
</div>
EDIT:
If I use console log on the last component it prints my "my_id_creation".
For the Father and Child I'm using the:
#Input() myID: string;
Are you getting an error? In any case, your father and child components need to define those id's as input, something along the lines of this:
#Component({
selector: 'father-component',
template: `
<div class="section rounded">
<div class="title">{{myTitle}}</div>
<app-list #glist
[id]="id"
</app-list>
</div>
`
})
export class FatherComponent {
#Input() id: number;
}

Nested Templates in Angular 2 [duplicate]

This question already has an answer here:
Passing Components in Angular2
(1 answer)
Closed 6 years ago.
I have a component, <DropDown></DropDown> and I want to let the user pass in a template for the list items in the DropDown.
Assuming they want to make a custom list item that has an image and text they would do something like this:
<DropDown [data]="myData">
<template>
<span> <img src="..."> Some Text <span>
</template>
</DropDown>
Inside the HTML of my DropDown component I have:
<div>
<ul>
<DropDownList [data]="data">
</DropDownList>
</ul>
</div>
In the DropDownList component I have the following HTML:
<li *ngFor="let item of data
(click)="handleOnSelect(item)">
[class.selected]="selectedItems.includes(item)">
<template [ngWrapper]="itemWrapper>
</template>
</li>
(I am using the template wrapper method from this post:
Binding events when using a ngForTemplate in Angular 2)
This method works if I have the li elements within the DropDown component's HTML. However, I want to have wrap the li's into a DropDownList component and pass the template the user gave from DropDown into DropDownList.
Is it possible to do this?
You could try the following solution:
#Component({
selector: 'DropDownList',
template: `
<li *ngFor="let item of items" (click)="handleOnSelect(item)">
<template [ngTemplateOutlet]="itemWrapper" [ngOutletContext]="{ $implicit: item }">
</template>
</li>`
})
export class DropDownListComponent {
#Input() itemWrapper: TemplateRef<any>;
#Input() items: any;
handleOnSelect(item) {
console.log('clicked');
}
}
#Component({
selector: 'DropDown',
template: `
<div>
<ul>
<DropDownList [items]="items" [itemWrapper]="itemWrapper">
</DropDownList>
</ul>
</div>`
})
export class DropDownComponent {
#Input() items: string[];
#ContentChild(TemplateRef) itemWrapper: TemplateRef<any>;
}
#Component({
selector: 'my-app',
template: `
<DropDown [items]="items">
<template let-item>
<h1>item: {{item}}</h1>
</template>
</DropDown>
`
})
export class App {
items = ['this','is','a','test'];
}
Plunker Example
The ngTemplateOutlet(^2.0.0-rc.2) directive has the same functionality as your custom directive NgWrapper
See also related questions:
Creating a dynamic repeater with ng-content transclusion with Angular2
Switch html templates dynamically during runtime on user action in angular 2

Categories

Resources