Show text when image is clicked - html

I'm trying to show some text underneath my header when the image I have is clicked. OnClick, it should show the paragraph of text underneath. However, I'm stuck on what is wrong with my current implementation.
Here's my html code so far:
I have a question and next to it is a plus sign for example. When I click on the plus sign, showAnswer goes from false to true and then it should showAnswer but the page loads with all the content already shown. How can I fix that?
<h1 class="question"> Foo?
<img (click)="showAnswer = !showAnswer" style="float:right;" src="images/ic-add.png"
class="ic_add"/></h1>
<p *ngIf="showAnswer" class="answer" > Bar</p>
<hr/>
<h1 class="question" >ABC
<img (click)="showAnswer = !showAnswer" style="float:right;" src="images/ic-add.png" class="ic_add"/>
</h1>
<p *ngIf="showAnswer" class="answer">123</p>
<hr/>
ts:
export class QuestionsComponent {
public showAnswer = false;
constructor(){
}
}

There is no problem in your code.
I have made an example.
You could check it.
UPDATED
Support multiple question by ngFor.
//our root app component
import {Component, View, CORE_DIRECTIVES, FORM_DIRECTIVES} from 'angular2/angular2'
import {Question} from './question'
#Component({
selector: 'my-app',
bindings: []
})
#View({
template: `
<question *ng-for="#el of questionArray; #idx = index"></question>
`,
directives: [CORE_DIRECTIVES, FORM_DIRECTIVES, Question]
})
export class App {
questionArray: Object[] = [1,2];
}
import {Component, View, CORE_DIRECTIVES} from 'angular2/angular2'
#Component({
selector: 'question',
bindings: []
})
#View({
template: `
<h1 class="question"> Foo?
<img (click)="clicked()" style="float:right;" src="images/ic-add.png"
class="ic_add"/></h1>
<p *ng-if="showAnswer" class="answer"> Bar</p>
<hr/>
`,
directives: [CORE_DIRECTIVES]
})
export class Question {
showAnswer: bool = false;
clicked() {
this.showAnswer = !this.showAnswer;
}
}

Related

initialize html tag from angular type-script

as shown in the below angular type script code, i would like to refer to the divisions mentioned in the below posted .html code using document.getElementById
the result of the log statement is null
please let me know how correctly to referece an html-tag in type-script
.ts:
export class GridCellPopupOverlayComponent implements OnInit {
isVisible = true
container: any
content
closer: any
overlay: any
AoC: any
AvgH: any
Dist: any
I: any
constructor() {
}
initHTMLElements() {
console.log("html init")
this.container = document.getElementById('idGridCellInfoPopupDiv');
this.AoC = document.getElementById('idGridCellInfoAoCValueDiv');
this.AvgH = document.getElementById('idGridCellInfoAvgHValueDiv');
this.Dist = document.getElementById('idGridCellInfoDistValueDiv');
this.I = document.getElementById('idGridCellInfoIValueDiv');
this.closer = document.getElementById('gridCellInfoPopup-closer');
console.log("this.AoC:",this.AoC)
}
}
html:
<div *ngIf="isVisible" id="idGridCellInfoPopupDiv" class="ol-popup">
<!-- <span id="idGridCellLabel" class="label label-success">dsfdsfsa</span> -->
<div class="alert alert-success alert-sm" role="alert">
<div class="alert-items">
<div class="alert-item static">
<div class="alert-icon-wrapper">
<clr-icon class="alert-icon" shape="check-circle"></clr-icon>
</div>
<div id="idGridCellAlertText"class="alert-text">
</div>
</div>
</div>
<!-- <button type="button" class="close" aria-label="Close">
<clr-icon aria-hidden="true" shape="close"></clr-icon>
</button> -->
</div>
<div id="idGridCellInfoAoCValueDiv"></div>
<div id="idGridCellInfoAvgHValueDiv"></div>
<div id="idGridCellInfoDistValueDiv"></div>
<div id="idGridCellInfoIValueDiv"></div>
You can get the elements from the .html by using #ViewChild/#ViewChildren decorators. Behind the scenes they are using document.getElementById. This is the correct way in Angular.
Also watch out for ngAfterViewInit lifeycle method in which you can access your references. View queries are set before the ngAfterViewInit callback is called. (form Angular documentation)
Here is the reference: https://angular.io/api/core/ViewChild
Btw, you can omit static: false since it's default.
TS file
import { HelloComponent } from './hello.component';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements AfterViewInit {
name = 'Angular';
#ViewChild('pRef', {static: false}) pRef: ElementRef;
ngAfterViewInit() {
console.log(this.pRef.nativeElement.innerHTML);
this.pRef.nativeElement.innerHTML = "DOM updated succesfully!!!";
}
}
Template file
<hello name="{{ name }}" ></hello>
<p #pRef>
Start editing to see some magic happen :)
</p>```

What is the purpose of <app-control-message> in angular 8 and how it is used?

I need to create a button for uploading a file in my form. I am using tag in my html but it is throwing an error : Can't bind to 'control' since it isn't a known property of 'app-contorl-message'.
Here is my html code -
<div class="col-lg-6">
<div class="form-group">
<div class="custom-file">
<input *ngIf="mode == 'CREATE'" type="file" (change)="onFileSelect($event)"
accept=".jpg,.jpeg,.png"/>
<app-contorl-message [control]="form.get('file')"></app-contorl-message>
</div>
</div>
</div>
here is def of onSelect($event) :
onFileSelect(event) {
this.form.get('file').setValue(event.srcElement.files);
this.fileData = event.srcElement.files;
console.log(event);
}
Thanks in advnace!
In your AppControlMessageComponent you need to create an #Input() named control. To learn more about inputs and output, visit: https://angular.io/guide/inputs-outputs
app-control-message.component.ts
import { Component, OnInit, Input } from "#angular/core";
#Component({
selector: "app-app-control-message",
templateUrl: "./app-control-message.component.html",
styleUrls: ["./app-control-message.component.css"]
})
export class AppControlMessageComponent implements OnInit {
#Input() control; // Input whose value parent component will provide
constructor() {}
ngOnInit() {}
}

How can we create modal pop-up in angular from scratch

Need to create a modal popup on button click,
is there any way to make it from scratch without adding any extra dependency for it,
with the below method, I am getting the fully functional modal, but have no confidence whether this is a good way in angular or not,
please suggest
HTML
<button class="hl-sort" (click)="openSortingModal()">
Sort
</button>
<div class="modal-container" *ngIf="modalContent">
<h1>i am modal content</h1>
<button (click)="closeModal()">Close</button>
</div>
components.ts
modalContent = false;
openSortingModal(){
this.modalContent = true;
console.log('clicked')
}
closeModal(){
this.modalContent = false;
}
If you don't want to add any extra dependency, I suggest you create a re-usable component using HTML + CSS as follows:
import { Component, OnInit, ViewChild, ElementRef } from '#angular/core';
#Component({
selector: 'app-modal',
template: `
<div #myModal class="container">
<div class="content">
<p>Some content here...</p>
<button (click)="close()">Close</button>
</div>
</div>
`,
styleUrls: ['./modal.component.css']
})
export class ModalComponent {
#ViewChild('myModal', {static: false}) modal: ElementRef;
open() {
this.modal.nativeElement.style.display = 'block';
}
close() {
this.modal.nativeElement.style.display = 'none';
}
}
Then use it in your container:
import { Component, ViewChild } from '#angular/core';
import { ModalComponent } from './modal/modal.component';
#Component({
selector: 'my-app',
template: `
<app-modal #modal></app-modal>
<p>
Open a Pure HTML + CSS with Angular
</p>
<button (click)="openModal()">Open Modal</button>
`,
styleUrls: []
})
export class AppComponent {
#ViewChild('modal', {static: false}) modal: ModalComponent
openModal() {
this.modal.open();
}
}
See a working example here: https://stackblitz.com/edit/angular-modal-html-css
I hope it helps!
If you do not want to reinvent the wheel, you can use this
https://ng-bootstrap.github.io/#/components/modal/examples
well, if you want to "re-invent the wheel", don't forget close the modal when you click outside
improving the Luixaviles's answer, the component modal can be like
<div #myModal class="container" (click)="tryClose()">
<div #content class="content">
<ng-content></ng-content>
</div>
</div>
Well, you see that I make a function "tryClose" if you click on the div "myModal", this function check if we click but we don't click inside "content"
tryClose() {
const clickTarget = event.target as HTMLElement;
if (!(this.content.nativeElement as HTMLElement).contains(clickTarget))
this.close();
}
Using <ng-content> allow us write in app.component some like
<app-modal #modal>
<p>Some content here...</p>
<button (click)="modal.close()">Close</button>
</app-modal>
<p>
Open a Pure HTML + CSS with Angular
</p>
<button (click)="modal.open()">Open Modal</button>
The rest of code in modal component is simple:
export class ModalComponent {
#ViewChild("myModal", { static: false }) modal: ElementRef;
#ViewChild("content", { static: false }) content: ElementRef;
open() {
this.modal.nativeElement.style.display = "block";
}
close() {
this.modal.nativeElement.style.display = "none";
}
}
See the Luixaviles's forked stackblitz
Update a simple stopPropagation makes the thinks easer
<div #myModal class="container" (click)="close()">
<div (click)="$event.stopPropagation()" class="content">
<ng-content></ng-content>
</div>
</div>
Obviously it is a good idea to create your own component rather using a third party. Just make sure, your popup must be a reusable or dynamic popup.

Hide elements using Typescript

I'm new to Typescript and Angular Material. I want to hide elements inside elements like this.
<div id="abc">
<div id="123">
<p>Hello!</p>
</div>
<p>World</p>
</div>
<div id="def">
<p>Hello World</p>
</div>
I want to hide div block(id:123).I tried in this way.
var formElement = <HTMLFormElement>document.getElementById('123');
formElement.style.display='block';
It gets an error saying Cannot read property 'style' of null.... How can I solve this problem.
This is not the way to hide elements in Angular. Bind your element's style attribute to a boolean, like this:
<form [style.display]="isVisible ? 'block' : 'none'">... contents</form>
And in your component class:
this.isVisible = false; // whenever you need to hide an element
Or you can use *ngIf:
<form *ngIf="isVisible">... contents</form>
Please, note that *ngIf removes the node and its children completely from the DOM tree completely if the conditions turns to false, and fully recreates them from scratch when the condition turns true.
You can access the dom element using ViewChild with #localvariable as shown here,
import {Component, NgModule,ViewChild,ElementRef} from '#angular/core'
import {BrowserModule} from '#angular/platform-browser'
#Component({
selector: 'my-app',
template: `
<div id="abc">
<div #id id="123">
<p>Hide!</p>
</div>
<p>World</p>
</div>
<div id="def">
<p>Hello World</p>
</div>
`,
})
export class App {
name:string;
#ViewChild('id') el:ElementRef;
constructor() {
this.name = `Angular! v${VERSION.full}`
}
ngAfterViewInit()
{
this.el.nativeElement.style.display='none';
console.log(this.el.nativeElement);
}
}
#NgModule({
imports: [ BrowserModule ],
declarations: [ App ],
bootstrap: [ App ]
})
export class AppModule {}
#Component({
selector: 'my-app',
template: `
<div #id>
<p>Hide This!</p>
</div>
<div>
<p>Hello World</p>
</div>
`,
})
export class AppComponent {
#ViewChild('id') id:ElementRef;
constructor() {}
ngOnInit()
{
this.id.nativeElement.hidden=true;
}
}
The simplest way to hide elements using DOM is
document.getElementById('123').hidden = true;
in typescript.

Building a wrapper directive (wrap some content / component) in angular2

I'm pretty new building directives with Angular2. What I want is to create a popup directive that will wrap the content with some css classes.
Content
Content can be pure text and headers like:
<div class="data">
<h2>Header</h2>
Content to be placed here.
</div>
Then I want to give this a directive attribute like: popup
<div class="data" popup>
<h2>Header</h2>
Content to be placed here.
</div>
What the directive should do, is to wrap the div inside, lets say:
<div class="some class">
<div class="some other class">
<div class="data">
<h2>Header</h2>
Content to be placed here.
</div>
</div>
</div>
The case i described so far, is this a attribute or structural directives.
import { Directive, ElementRef, HostListener, Input } from '#angular/core';
#Directive({
selector: `[popup]`
})
export class PopupDirective {
}
The other answer is related but different.
For something closer, see this: How to conditionally wrap a div around ng-content - my solution is for Angular 4, but the linked question has some hints about how this might be doable for Angular 2.
I solved this problem with a component and a directive combined. My component looks something like this:
import { Component, Input, TemplateRef } from '#angular/core';
#Component({
selector: 'my-wrapper-container',
template: `
<div class="whatever">
<ng-container *ngTemplateOutlet="template"></ng-container>
</div>
`
})
export class WrapperContainerComponent {
#Input() template: TemplateRef<any>;
}
and my directive like this:
import { Directive, OnInit, Input, TemplateRef, ComponentRef, ComponentFactoryResolver, ViewContainerRef } from '#angular/core';
#Directive({
selector: '[myWrapperDirective]'
})
export class WrapperDirective implements OnInit {
private wrapperContainer: ComponentRef<WrapperContainerComponent>;
constructor(
private templateRef: TemplateRef<any>,
private viewContainerRef: ViewContainerRef,
private componentFactoryResolver: ComponentFactoryResolver
) { }
ngOnInit() {
const containerFactory = this.componentFactoryResolver.resolveComponentFactory(WrapperContainerComponent);
this.wrapperContainer = this.viewContainerRef.createComponent(containerFactory);
this.wrapperContainer.instance.template = this.templateRef;
}
}
To be able to load your component dynamically, you need to list your component as an entryComponent inside your module :
#NgModule({
imports: [CommonModule],
declarations: [WrapperContainerComponent, WrapperDirective],
exports: [WrapperContainerComponent, WrapperDirective],
entryComponents: [WrapperContainerComponent]
})
export class MyModule{}
so the HTML in the end is:
<some_tag *myWrapperDirective />
Which renders as:
<my-wrapper-container>
<div class="whatever">
<some_tag />
</div>
</my-wrapper-container>
You can achieve this with a component attribute selector and Angular 2 Content Projection <ng-content>
#Component({
selector: 'my-app',
template: `
<div class="app">
<div class="data" myWrapper>
<h2>Header</h2>
Content to be placed here.
</div>
</div>
`
})
export class AppComponent {}
#Component({
selector: '[myWrapper]',
template: `
<div class="my-class">
<div class="my-sub-class">
<ng-content></ng-content>
</div>
</div>
`
})
export class MyComponent {
}