I want to take values from input to a function to alert
here is my html
<div class="container p-5 ">
<input #titleInput *ngIf="isClicked" type="text" class="col-4"><br>
<button (click)="OnClick()" class="btn btn-primary col-2 ">
Show
</button>
<button (click)="Send(titleInput.value)" class="btn btn-success col-2 m-3">
Send
</button>
</div>
and here is my componet.ts
import { Component} from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
Send(data: any) {
alert(data)
}
OnClick() {
this.isClicked=true;
}
title = 'demoproject1';
isClicked=false;
}
I want to get value from input field and I want get value into components function
Create Variable to store input value:
component.ts
...
export class AppComponent {
input: string;
...
Add FormsModule to your module.ts if not already imported
module.ts
import { FormsModule } from '#angular/forms';
setup ngModel on your HTML:
html:
<input type="text" [(ngModel)]="input" ></-input>
Important:
Dont forget to add a Route to the component in your app-routing.module.ts
ngModel Docs
#ViewChild('titleInput') titleInput:
ElementRef;
ngAfterViewInit() {
// Put your logic here ...
}
i put the code here :
https://stackblitz.com/edit/angular-ivy-b4hcqw?file=src%2Fapp%2Fapp.component.ts,src%2Fapp%2Fapp.component.html
Related
I am working on an e-commerce app who's front-end is made in Angular 13.
The UI has a sidebar which I do not want to display on the product details page.
For this purpose, in app\app.component.ts I have:
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'E-commerce';
constructor(private router: Router) {}
ngOnInit() {}
/**
* Check if the router url contains the specified route
*
* #param {string} route
* #returns
* #memberof AppComponent
*/
hasRoute(route: string) {
return this.router.url.includes(route);
}
}
In app\app.component.html:
<div class="app-wrapper">
<app-navbar></app-navbar>
<div class="container">
<div class="row my-3">
<div *ngIf="!hasRoute('products/show/:id')" class="col-sm-6 col-md-4 col-lg-3">
<app-sidebar class="app-sidebar"></app-sidebar>
</div>
<div class="col-sm-6 col-md-8 col-lg-9">
<router-outlet></router-outlet>
</div>
</div>
</div>
<app-footer class="app-footer"></app-footer>
</div>
The problem
For a reason I have been unable to understand, this solution fails, and the sidebar is displayed anywhere on the app.
What am I doing wrong?
<div *ngIf="notProductDetails()" class="col-sm-6 col-md-4 col-lg-3">
<app-sidebar class="app-sidebar"></app-sidebar>
</div>
HTML ^^^
constructor() {}
public notProductDetails(): void {
return !window.location.pathname.startsWith('/products/show/');
}
TS
Simply use the window location to pull the pathname instead of injecting the router - remove the constructor injection. Also no need to pass in a prop value there, because you only have a single string you are asserting.
In that way, you are running that value just one time. In order to achieve this you can subscribe to the router events like this:
public showBar: boolean = true;
constructor(private readonly router: Router) {
this.router.events
.pipe(filter((event) => event instanceof NavigationEnd))
.subscribe(({ urlAfterRedirects }: NavigationEnd) =>
this.showBar = this.hasRoute(urlAfterRedirects)
);
}
<div *ngIf="showBar" class="col-sm-6 col-md-4 col-lg-3">
<app-sidebar class="app-sidebar"></app-sidebar>
</div>
In this way, you are updating the showBar value every time the navigation end.
In case someone may find it useful, here is the final solutions I have applied to this problem:
In app\app.component.ts:
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
title: string = 'E-commerce';
constructor(private router: Router) {}
ngOnInit() {}
routeIncludesNot(route: string) {
return !window.location.pathname.startsWith(route);
}
}
In app\app.component.html I have:
<div class="app-wrapper">
<app-navbar></app-navbar>
<div class="container">
<div class="row my-3">
<div *ngIf="routeIncludesNot('/products/show/')" class="col-sm-6 col-md-4 col-lg-3">
<app-sidebar class="app-sidebar"></app-sidebar>
</div>
<div [ngClass]="routeIncludesNot('/products/show/') ? 'col-sm-6 col-md-8 col-lg-9' : ''">
<router-outlet></router-outlet>
</div>
</div>
</div>
<app-footer class="app-footer"></app-footer>
</div>
See a "live demo" HERE.
I have 2 components.
The .html of parent component this is the code:
<div class="space">
<ng-container *ngFor="let item of items">
<ng-container [ngTemplateOutlet]="itemTemplate" [ngTemplateOutletContext]="{item: item}">
</ng-container>
</ng-container>
</div>
<ng-template #itemTemplate let-item="item">
<div class="host">
<img class='card-img-top'
src={{item.image}}
>
<p> </p>
<h6 class="title">{{item.projectTitle}}</h6>
<hr>
<ng-container *ngIf="item.type=='inactive'">
<button id="inactive"
class="btn btn-sm btn-warning py-0 custom-button text-uppercase">{{item.type}}</button>
</ng-container>
</div>
</ng-template>
All code since line: <ng-template #itemTemplate let-item="item">
It's necessary to show in the .html of the child component.
This is the .ts of parent component
import { AfterViewInit, Component, ComponentFactoryResolver, ViewChild, ViewContainerRef, OnInit, TemplateRef, Input, ContentChild } from '#angular/core';
import listProjects from './projects.json';
import { ChildComponent } from './child.component';
#Component({
selector: 'parent-view',
templateUrl: './parent.component.html',
styleUrls: ['./parent.component.scss'],
})
export class ParentComponent {
public items: any = listProjects;
#ContentChild('itemTemplate', { read: TemplateRef }) itemTemplate: ViewContainerRef;
How can show the <ng-template #itemTemplate let-item="item"> in other component?
The solution to this problem:
File: projects-tile-view-components.ts
export class ProjectsTileViewComponent {
#ViewChild('tileViewItems', { static: true }) tileViewItemTemplate: TileViewComponent;
public items = listProjects;
public type = 'etb';
constructor() {}
addItems(e) {
if (this.type === 'osd') {
this.type = 'etb';
} else {
this.type = 'osd';
}
}
}
the file projects-tile-view-components.html
<lib-tile-view [items]="items" #tileViewItems>
<ng-template #tileViewItem let-item>
<div [ngSwitch]="type">
<lib-osd-tile-view-item [item]="item" *ngSwitchCase="'osd'"></lib-osd-tile-view-item>
<lib-osd-tile-view-item [item]="item" *ngSwitchDefault></lib-osd-tile-view-item>
<lib-etb-tile-view-item [item]="item" *ngSwitchCase="'etb'"></lib-etb-tile-view-item>
</div>
</ng-template>
</lib-tile-view>
the file view-item.ts (interface)
export interface ViewItem {
item: any;
}
the file tile-view-components.html
<div>
<ng-container *ngFor="let item of items">
<ng-container *ngTemplateOutlet="tileViewItemTemplate; context: {$implicit: item}">
</ng-container>
</ng-container>
</div>
the file tile-view-item.components.ts
#Component({
selector: 'lib-tile-view',
templateUrl: './tile-view.component.html',
styleUrls: ['./tile-view.component.scss'],
})
export class TileViewComponent {
#Input()
public items: any;
#ContentChild('tileViewItem', { static: true }) tileViewItemTemplate;
}
the file osd-tile-view-components.ts
#Component({
selector: 'lib-osd-tile-view-item',
templateUrl: './osd-tile-view-item.component.html',
styleUrls: ['./osd-tile-view-item.component.scss'],
})
export class OsdTileViewItemComponent implements ViewItem {
#Input() item: any;
public projectView() {
alert('show project');
}
}
the file osd-tile-view-item.components.html
<div class="host" fxFlex="0 1 calc(100% - 32px)" fxFlex.lt-md="0 1 calc(100% - 32px)" fxFlex.lt-sm="100%" (click) = 'projectView()'>
<img class='img-fluid img-thumbnail' src={{item?.image}} alt='logo nih'>
<p> </p>
<h6 class="title">{{item?.projectTitle}}</h6>
<p class="small"><span class="text-muted small text-uppercase">ZIA ID
Number:</span>{{item?.number}}</p>
</div>
Thanks for your help
You need to share this TemplateRef in service (if you want to have access in every component in your application), and then in other component you can read this reference and do something with it - because if you want to pass this reference only to child, then you can use #Input() in child component, but if it should be available across all components, then you need to create service.
service:
#Injectable({
providedIn: 'root'
})
export class TemplateService {
someTemplate: TemplateRef<any>;
}
componentA:
#Component({
selector: 'parent-view',
templateUrl: './parent.component.html',
styleUrls: ['./parent.component.scss'],
})
export class ParentComponent {
public items: any = listProjects;
#ViewChild('itemTemplate', { read: TemplateRef }) set itemTemplate(value) {
this.ts.someTemplate = value;
}
construtor(private ts: TemplateService) {}
}
then in any other component, you can read this template reference
componentB:
#Component({
selector: 'component-b',
templateUrl: './component-b.component.html',
styleUrls: ['./component-b.component.scss'],
})
export class ComponentBComponent {
get itemTemplateReference() {
return this.ts.itemTemplate;
}
construtor(private ts: TemplateService) {}
}
.html of componentB
<ng-container [ngTemplateOutlet]="itemTemplateReference"></ng-container>
And it should render the same <ng-template>
I am Using Angular 7. i run this cmd ng build --prod build for protection.
That time i am caching this Error( Property 'service' is private and only accessible within class 'LoginComponent'):
ERROR in src\app\login\login.component.html(5,33): : Property 'service' is private and only accessible within class 'LoginComponent'.
src\app\login\login.component.html(18,104): : Property 'service' is private and only accessible within class 'LoginComponent'.
It's my HTML Code:
<div id="login_section" class="d-flex justify-content-center align-items-center">
<div class="login_cnt col-8 row">
<div class="col-6 d-flex justify-content-center py-4">
<form class="col-8" [formGroup]="service.loginform">
<h2 class="text-center">User Login</h2>
<mat-form-field class="col-12">
<input matInput type="text" placeholder="Username" formControlName="username" >
<mat-error>Username is Required</mat-error>
</mat-form-field>
<mat-form-field class="col-12">
<input matInput [type]="hide ? 'password' : 'text'" formControlName="password" placeholder="Password">
<mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility_off' : 'visibility'}}</mat-icon>
<mat-error>Password is Required</mat-error>
</mat-form-field>
Forgot Password
<button mat-raised-button color="primary" class="float-right" [routerLink]="['/home']" [disabled]="service.loginform.invalid">Login</button>
</form>
</div>
</div>
</div>
It's My TS File:
import { Component, OnInit } from '#angular/core';
import { LoginService } from '../shared/login.service';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
username : string;
password: string;
hide = true;
constructor(private service: LoginService) { }
ngOnInit() {
}
}
when running ng serve am not catching it .
There are 2 ways to resolve this.
1.
Change private service: LoginService to public service: LoginService
As you are using AOT during compilation, you can not access private properties of your component in your HTML template.
2.
If you want to keep your service private, you can provide a public method in the controller which returns the service properties. You can call this method from your HTML template. It would be something like this:
Template:
<div id="login_section" class="d-flex justify-content-center align-items-center">
<div class="login_cnt col-8 row">
<div class="col-6 d-flex justify-content-center py-4">
<form class="col-8" [formGroup]="getLoginForm()"> <!-- Change here-->
<h2 class="text-center">User Login</h2>
<mat-form-field class="col-12">
<input matInput type="text" placeholder="Username" formControlName="username" >
<mat-error>Username is Required</mat-error>
</mat-form-field>
<mat-form-field class="col-12">
<input matInput [type]="hide ? 'password' : 'text'" formControlName="password" placeholder="Password">
<mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility_off' : 'visibility'}}</mat-icon>
<mat-error>Password is Required</mat-error>
</mat-form-field>
Forgot Password
<button mat-raised-button color="primary" class="float-right" [routerLink]="['/home']" [disabled]="getLoginForm().invalid">Login</button> <!-- Change here-->
</form>
</div>
</div>
</div>
Controller:
import { Component, OnInit } from '#angular/core';
import { LoginService } from '../shared/login.service';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
username : string;
password: string;
hide = true;
constructor(private service: LoginService) { }
ngOnInit() {
}
getLoginForm() {
return this.service.loginform;
}
}
P.S: I have not tested the second one myself for the moment.
You need to make your access specifier to be public to make it accessible
constructor(public service: LoginService) { }
Seems that you're using Ahead-of-Time compilation (while build), and you're trying to access a private member (service) of the component in its template [disabled]="service.loginform.invalid", service.loginform. But it must be public in the case of using it in template and ahead-of-time compilation:
constructor(private service: LoginService) { }
should be:
// your component: change private service to public service
constructor(public service: LoginService) { }
// then you can use it like this in the template of your component:
[formGroup]="service.loginform"
[disabled]="service.loginform.invalid"
If you need a service be private and still need to use some of its members in the template of your component, use get or other methods (public) to return that members:
// your component
constructor(private service: LoginService) { }
get loginForm() {
return this.service.loginform;
}
get loginIsInvalid(): boolean {
return this.service.loginform.invalid;
}
// then in the template of your component you can use:
[formGroup]="loginform"
[disabled]="loginIsInvalid"
Do you have concerns about having to call a function instead of using just a variable in the template?
Catch this self-executing function tip:
Template:
<form class="col-8" [formGroup]="loginform"> <!-- Change here-->
Controller:
import { Component, OnInit } from '#angular/core';
import { LoginService } from '../shared/login.service';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
username : string;
password: string;
hide = true;
constructor(private service: LoginService) { }
ngOnInit() {
}
loginform = (() -> this.service.loginform)(); /* Change here */
}
This can be useful if you need to access some internal fields of that variable inside the template.
<form class="col-8" [formGroup]="loginform.SOME_FIELD.INNER_PROP">
instead of
<form class="col-8" [formGroup]="getLoginForm().SOME_FIELD.INNER_PROP">
It looks more convenient and readable, imho.
I'm developing an app with Angular 2.0/meteor, and I don't know how to bind an input to md-slider.
Here's the component html :
<div class="panel-body">
<form [formGroup]="filtreForm" #f="ngForm">
<span class="panel-title"> <i class="glyphicon glyphicon-retweet"> Paramétrages 0 </i></span>
<md-slide-toggle>On</md-slide-toggle>
<div *ngFor="let filtre of filtres | async">
<div *ngFor="let filtr of filtre.arguments">
<span class="panel-title" > <i class="glyphicon glyphicon-retweet"> {{filtr.name}} </i></span>
<md-input-container class="example-full-width" >
<input mdInput placeholder="{{filtr.name}}" formControlName="{{filtr.name}}" value="{{filtr.value}}">
</md-input-container>
<md-slider
thumb-label
[min]="'0'"
[max]="'200'"
[value]="filtr.value">
</md-slider>
</div>
</div>
<div class="btn-group people-pager">
<button type="button" class="btn btn-success btn-quirk" (click)="appliquerFiltre()"><i class="fa fa-tencent-weibo Try it"></i> Appliquer ce filtre</button>
</div>
</form>
</div>
Here's the component ts :
import {Component, ViewEncapsulation, OnInit, NgZone, Input} from '#angular/core';
import { Router } from '#angular/router';
import { Meteor } from 'meteor/meteor';
import { Observable } from 'rxjs';
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
//Collection import
import { Filtres } from '../../../../both/collections/filtres.collection';
import {Filtre} from "../../../../both/models/filtre.model";
import template from './tpl.dashboard.component.html';
#Component({
selector: 'traitement_par_lot',
encapsulation: ViewEncapsulation.None,
template
})
export class TPLcomponent implements OnInit{
filtres: Observable<Filtre[]>;
filtreForm: FormGroup;
constructor(
private formBuilder: FormBuilder, private router: Router
) {}
ngOnInit(){
this.filtreForm = this.formBuilder.group({
spread:['',Validators.required],
density:['',Validators.required],
curviness:['',Validators.required],
reseed:['',Validators.required],
});
this.filtres = Filtres.find({}).zone();
console.log(this.filtres);
}
appliquerFiltre(){
}
}
This doesn't work. for now i can get the initial value from the slider but it's doesn't change when i slide
Thanks in advance
For update the value while slidering, you can use change or input event of md-slider, and get the current value from it's event.value.
change event will be fired only after the end of you slide.
input event will be fired immediately when the value of slider changes
you can choose the better one for your situation.
take a look at this plunker.
I'm trying to show a simple Modal with Ng2-bootstrap as per the following page: https://ng-bootstrap.github.io/#/components/modal
However I am getting errors such as:
Error in ./AppComponent class AppComponent - inline template:7:0 caused by: Missing modal container, add <template ngbModalContainer></template> to one of your application templates.
ORIGINAL EXCEPTION: Missing modal container, add <template ngbModalContainer></template> to one of your application templates.
What am I doing wrong? I've got the following code to try and make this work:
Index.html:
<body>
<app-root>Loading...</app-root>
<template ngbModalContainer></template>
</body>
app.module.ts:
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
...
#NgModule({...
imports: [
BrowserModule,
FormsModule,
HttpModule,
NgbModule.forRoot() ...
app.component.ts:
import { NgbModal, NgbActiveModal, ModalDismissReasons } from '#ng-bootstrap/ng-bootstrap';
import { SasModalComponent } from './sas-modal/sas-modal.component';
...
constructor(..., private modalService: NgbModal){
}
...
open() {
console.log("trying to open");
const modalRef = this.modalService.open(SasModalComponent);
}
app.component.html
<button class="btn btn-lg btn-outline-primary" (click)="open(content)">Launch demo modal</button>
sas-modal.component.ts
import { NgbModal, NgbActiveModal, ModalDismissReasons } from '#ng-bootstrap/ng-bootstrap';
...
#Component({
selector: 'sas-modal',
templateUrl: './sas-modal.component.html',
styleUrls: ['./sas-modal.component.css']
})
export class SasModalComponent {
closeResult: string;
constructor(private modalService: NgbModal) {}
open(content) {
this.modalService.open(content);
}
}
sas-modal.component.html:
<template #content let-c="close" let-d="dismiss">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" (click)="d('Cross click')">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">Modal title</h4>
</div>
<div class="modal-body">
<p>One fine body…</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" (click)="c('Close click')">Close</button>
</div>
</template>
sas-component.ts should be : -
import { NgbModal, NgbActiveModal, ModalDismissReasons } from '#ng-bootstrap/ng-bootstrap';
...
#Component({
selector: 'sas-modal',
templateUrl: './sas-modal.component.html',
styleUrls: ['./sas-modal.component.css']
})
export class SasModalComponent {
closeResult: string;
constructor(private activeModal: NgbActiveModal) {}
}
app.module.ts Should contain SasModuleComponent in the declaration array and a
entryComponent field that contains SasModuleComponent : -
#NgModule({
imports: [ BrowserModule,
FormsModule , HttpModule, NgbModule.forRoot()],
declarations: [ AppComponent, SasModalComponent],
bootstrap: [ AppComponent ],
entryComponents: [SasModalComponent]
})
You need a entryComponent field in #NgModule()in your module file because you are loading the SasModuleComponent dynamically here this.modalService.open(SasModalComponent).
Try adding <template ngbModalContainer></template> in app-root template
Example:
#Component({
selector: 'app-root',
template: '<template ngbModalContainer></template>'
})
saurav1405's answer provided me with enough useful information to figure this out, however his solution didn't 100% work for me.
For this reason I've upvoted saurav1405's response, but couldn't claim is as the answer as I've had to do a bit more to get it to work for me.
The main difference was having a seperate control component and content component.
This is how I got it working:
>> app.module.ts
Note: saurav1405 suggested putting ModalContentComponent into declarations, (possibly a typo after reviewing his comments again).
but you need to put the actual modal custom modal components in here (in this case SasModalComponent & SasModalContent).
And the content component (SasModalContent) needs to be the entry component.
import { SasModalComponent, SasModalContent } from './sas-modal/sas-modal.component';
...
#NgModule({
declarations: [
AppComponent,
SasModalComponent,
SasModalContent
],
entryComponents: [SasModalContent],
...
>> app.component.html:
The ngbModalContainer declaration should be along side the component declaration in the parent component html template, not in the index.html, which I think was the main reason I was getting the errors posted in the question.
<template ngbModalContainer></template>
<sas-modal-component></sas-modal-component>
>> sas-modal.component.ts:
This file combines both the control component [sas-modal-component] (that opens the content / template) and the content component [sas-modal-content] (that has the reference to the active modal and modal template).
import {Component, Input, Compiler } from '#angular/core';
import {NgbModal, NgbActiveModal} from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'sas-modal-content',
templateUrl: 'sas-modal-content.html'
})
export class SasModalContent {
#Input() name;
constructor(public activeModal: NgbActiveModal) { }
}
#Component({
selector: 'sas-modal-component',
templateUrl: 'sas-modal.component.html'
})
export class SasModalComponent {
constructor(private modalService: NgbModal, private compiler: Compiler) { }
open() {
//this.compiler.clearCacheFor(SasModalContent); //Only use when the template is caching when you don't want it to.
const modalRef = this.modalService.open(SasModalContent);
modalRef.componentInstance.name = 'World';
}
}
>> sas-modal.component.html: Contains the button / control to open the modal
<h2> Click the button to open the modal</h2>
<button class="btn btn-lg btn-outline-primary" (click)="open()">Launch demo modal</button>
>> sas-modal-content.html: Holds the modal template - can be whatever you want
<div class="modal-header">
<button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">Hi there!</h4>
</div>
<div class="modal-body card-info">
<h3 style="color: white;">So nice to meet you</h3>
<h4 style="color: white;">This modal is great!</h4>
</div>
<div class="modal-footer ">
<button type="button" class="btn btn-secondary" (click)="activeModal.close('Close click')">Close</button>
</div>