I have a form which allows me to create a new record or update an existing one. Right now the text of the button is submit. Based on if I call the form with an optional parameter which in my case is the id of the record to edit I set my form mode as create or update. What I want is to be able to set the text displayed as either create or update but I have not found a way to change the text from my controller. I can set all field values and enable or disable the submit button but have not found a way to set the Text on button. Can this be done and if not is there a work around
In your ts file.
export class AppComponent {
buttontext="Create"
name = 'Angular';
}
In your HTML File
<button>{{buttontext}}</button>
You can change button text accordingly.In your functions
See here-https://stackblitz.com/edit/angular-wsxkz9
If you are looking for some other solution you have to create your own directive
CustomDirective.ts file
import { Directive, ElementRef, Input, Renderer2 } from '#angular/core';
#Directive({ selector: '[myHidden]' })
export class HiddenDirective {
constructor(public el: ElementRef,private renderer: Renderer2) {}
#Input() myHidden: boolean;
ngOnInit(){
// Use renderer to render the emelemt with styles
console.log(this.myHidden)
if(this.myHidden) {
this.renderer.setProperty(this.el.nativeElement, 'innerHTML', 'Create');
}
else{
this.renderer.setProperty(this.el.nativeElement, 'innerHTML', 'Delete');
}
}
}
app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';
import { HiddenDirective } from './customdirective';
#NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ AppComponent, HelloComponent,HiddenDirective ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
val="true";
name = 'Angular';
}
app.component.html
<hello name="{{ name }}"></hello>
<p>
Start editing to see some magic happen :)
</p>
<button [myHidden]="val"></button>
See this- https://stackblitz.com/edit/angular-ktf7e3
Related
I have got a problem with String Interpolation.
So I try to make string interpolation according to what the teacher does in the course of Angular
i am doing.
I have a server.component.ts file which is exactly what teacher does in the course.
import { Component } from "#angular/core";
#Component ({
selector: 'app-servers',
templateUrl: './server.component.html'
})
export class ServerComponent {
serverId = 10;
serverStatus = 'offline'
}
And then I try to put it on the server.component.html so it appeared on the browser:
<p>Server with ID {{ serverId }} is {{ serverStatus }}</p>
I have checked multiple times and it seems like I have exactly the same setting that the teacher showed in the course. He has it written in the browser, and I do not.
Here are my other "settings"
app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
styles: [`
h1{
color: red
}
`]
})
export class AppComponent {
name = 'Wojtek';
}
**app.component.html
**
<div class="container">
<div class="row">
<div class="col-xs-12">
<h1>Hellloo!!!!</h1>
<input type="text">
<p>{{ name }}</p>
<hr>
<app-success-alert></app-success-alert>
<app-warning-alert></app-warning-alert>
</div>
</div>
</div>
app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { AppComponent } from './app.component';
import { ServerComponent } from './server/server.component';
import { ServersComponent } from './servers/servers.component';
import { SuccessAlertComponent } from './success-alert/success-alert.component';
import { WarningAlertComponent } from './warning-alert/warning-alert.component';
#NgModule({
declarations: [
AppComponent,
ServerComponent,
ServersComponent,
SuccessAlertComponent,
WarningAlertComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Also the thing is with implements OnInit in the export class line, in the course it works, however in my VSCode it does not really want to, any ideas?
Please it you may help me I would be really grateful!
I have tried to watch multiple youtube videos, also I came back to the course to rewatch it
It looks like your are missing the server-component in your app-component template. Put <app-servers></app-servers> somewhere in your app-component template.
I'm practicing the use of Anuglar Material Design components. I have gone through the regular steps to add Angular Material using 'ng add #angular/material' and selected one of the themes and okayed other defaults.
Everything works well, except that the form inputs are not visible in any of the browsers. They become visible only after intuitively clicking on the screen, guessing where the input maybe present. When I focus out of the input, the input field disappears
//app module ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import {MatInputModule} from '#angular/material/input'
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
MatInputModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
//app component ts
import { Component, NgModule } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
title = 'ang-mat-design';
}
<!--no code added -->
<mat-form-field appearance = "fill">
<input matInput placeholder = "Input">
<mat-hint>Sample Hint</mat-hint>
</mat-form-field>
I have an application where my requirement is upon a button click (present in header component) the form field in another component will get updated. But the problem is the value is getting set in the form control variable but is not reflecting in UI. This is the sample code I've created. You can see on button click in console log that the form has the value but is not rendered in UI. Below I am showing my code what I have done so far :
Child Component
// In TS
test = this.fb.group({
sample: [""]
});
// In HTML
<form [formGroup]="test">
<input placeholder="Sample" formControlName="sample" />
</form>
Header Component
// In TS
import { ChildComponent } from "../child/child.component";
constructor(private child: ChildComponent) {}
set() {
this.child.test.patchValue({
sample: "fetched value"
});
console.log(this.child.test.value);
}
// In HTML
<button (click)="set()">ABC</button>
app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { AppComponent } from './app.component';
import { HeaderComponent } from './header/header.component';
import { ChildComponent } from './child/child.component';
import { AppRouterModule } from './router/router.module';
#NgModule({
imports: [ BrowserModule, FormsModule, AppRouterModule, ReactiveFormsModule ],
declarations: [ AppComponent, HeaderComponent, ChildComponent ],
providers: [ ChildComponent ], // Specified child component to access through different component
bootstrap: [ AppComponent ]
})
export class AppModule { }
app.component.html
<app-header></app-header>
<router-outlet></router-outlet>
So this is my code. Can anyone tell me where the problem is lying ?
That isn't how the component interaction works in Angular. To share data among components, you could either use EventEmitter for related components or a singleton service for unrelated components.
Here is an illustration using a singleton service
share.service.ts
import { Injectable } from "#angular/core";
import { ReplaySubject } from "rxjs";
#Injectable()
export class ShareService {
public headerClickSrc = new ReplaySubject<any>(1);
public headerClick$ = this.headerClickSrc.asObservable();
constructor() {}
}
header.component.ts
import { Component } from "#angular/core";
import { ShareService } from "../share.service";
#Component({
selector: "app-header",
templateUrl: "./header.component.html"
})
export class HeaderComponent {
constructor(private share: ShareService) {}
set() {
this.share.headerClickSrc.next("fetched value");
}
}
child.component.ts
export class ChildComponent implements OnInit, OnDestroy {
closed$ = new Subject<any>();
constructor(private fb: FormBuilder, private share: ShareService) {}
test = this.fb.group({
sample: [""]
});
ngOnInit() {
this.share.headerClick$.pipe(
takeUntil(this.closed$)
).subscribe({
next: value => {
this.test.patchValue({
sample: value
});
console.log(this.test.value);
}
});
}
ngOnDestroy() {
this.closed$.next(); // <-- close open subscriptions
}
}
I've modified your Stackblitz
i have a page with main parent element and two child elements quite like this.
how can i focus on the text box in the child2 component, when clicked on the button on child 1 component.
child 1 component is actually the header section of my page. so there may also be cases like child1 is always visible, but instead of child2, there is some different component on display. then when i click on the button on child1, it should route to child2 and then scroll down and focus on the required text box of child 2..
how to implement this function in angular.
First of All you have to add the routing to your Child2(Assuming it as a class name) So that when user clicks the button on your header it is routed to Child2.
1.<button class="header" [routerLink]="['Child2']">Child2</button>
//Child2 is the name of child2 Component
2.And then use Angular life cycle hooks -> ngOnInit() {} ngOnInit is a life cycle hook called by Angular to indicate that the Angular is done creating the component.
And place some typescript code to make the textbox in focus.
<input type="text">Go to bottom</input>
<input type="text" id="textbox"></footer>
You can build some approach over the above example.
or
document.getElementById("textbox").click();
This will bring in focus into the textbox that is present in the component child2
Here is how you can implement this
Create one service will have to methods
Put in app.module.ts providers
Now inject this SharedService to child-one-component.ts and call setData() method of this service where we are setting value in observable
Now inject same SharedService to child-two-component.ts and call getData() method of service onInit() will subscribe to observable at the same time when you click on setData()
app.component.html
<app-child-one></app-child-one>
<app-child-two></app-child-two>
child-one.html
<div style="border: 2px solid black; padding:15px; margin-bottom:3px">
<p>child-one </p>
<button (click)="setFocus()">Set Focus</button>
<button (click)="removeFocus()" style="margin-left:10px;">Remove Focus</button>
</div>
child-one.ts
import { Component, OnInit, EventEmitter } from '#angular/core';
import { SharedService } from '../shared.service';
#Component({
selector: 'app-child-one',
templateUrl: './child-one.component.html',
styleUrls: ['./child-one.component.css']
})
export class ChildOneComponent implements OnInit {
constructor(private sharedService: SharedService) { }
ngOnInit() {
}
setFocus() {
this.sharedService.setData(true);
}
removeFocus() {
this.sharedService.setData(false);
}
}
child-two.html
<div style="border: 2px solid black; padding:25px 15px;">
<p>child-two </p>
<input type="text" placeholder="Enter text" #input/>
</div>
child-two.ts
import { Component, OnInit, ViewChild, ElementRef } from '#angular/core';
import { SharedService } from '../shared.service';
#Component({
selector: 'app-child-two',
templateUrl: './child-two.component.html',
styleUrls: ['./child-two.component.css']
})
export class ChildTwoComponent implements OnInit {
#ViewChild('input', {static: true}) private input: ElementRef;
constructor(private sharedService: SharedService) { }
ngOnInit() {
// will get called when user click on Set Focus button
this.sharedService.getData().subscribe((response: any)=> {
if(response) {
this.input.nativeElement.focus(); // will set focus into input here
} else {
this.input.nativeElement.blur();
}
})
}
}
app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { AppComponent } from './app.component';
import { ChildOneComponent } from './child-one/child-one.component';
import { ChildTwoComponent } from './child-two/child-two.component';
import { SharedService } from './shared.service';
#NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ AppComponent, ChildOneComponent, ChildTwoComponent ],
bootstrap: [ AppComponent ],
providers: [SharedService]
})
export class AppModule { }
shared.service.ts will use this service to send message from one component to another.
import { Injectable } from '#angular/core';
import { Observable, Subject } from 'rxjs';
#Injectable()
export class SharedService {
private subject$ = new Subject<any>();
constructor() { }
setData(data) {
this.subject$.next(data);
}
getData() {
return this.subject$.asObservable();
}
}
Here is working demo https://stackblitz.com/edit/santosh-angular-set-focus-in-input-from-another-component
I am trying to add the components dynamically in angular4.
I checked with other questions, But i cant find solution.
I got the error
ERROR TypeError: Cannot read property 'createComponent' of undefined
on dynamic components.
adv.component.ts
import { Component, OnInit, AfterContentInit, ViewChild, ViewContainerRef, ComponentFactoryResolver } from '#angular/core';
import { SampleComponent } from '../sample/sample.component';
#Component({
selector: 'app-adv',
templateUrl: './adv.component.html',
styleUrls: ['./adv.component.css']
})
export class AdvComponent implements OnInit, AfterContentInit {
#ViewChild('container', {read:'ViewContainerRef'}) container;
constructor(private resolver : ComponentFactoryResolver) { }
ngOnInit() {
}
ngAfterContentInit(){
const sampleFactory = this.resolver.resolveComponentFactory(SampleComponent);
this.container.createComponent(sampleFactory);
}
}
adv.component.html
<div #container></div>
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { AdvComponent } from './adv/adv.component';
import { SampleComponent } from './sample/sample.component';
#NgModule({
declarations: [
AppComponent,
AdvComponent,
SampleComponent
],
entryComponents:[
SampleComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
About ngAfterViewInit in docs:
Respond after Angular initializes the component's views and child
views.
while ngAfterContentInit:
Respond after Angular projects external content into the component's
view.
So the child view is not ready in ngAfterContentInit, so move this part
ngAfterContentInit(){
const sampleFactory = this.resolver.resolveComponentFactory(SampleComponent);
this.container.createComponent(sampleFactory);
}
to
ngAfterViewInit() {
const sampleFactory = this.resolver.resolveComponentFactory(SampleComponent);
this.container.createComponent(sampleFactory);
}
Also change:
#ViewChild('container', {read:'ViewContainerRef'}) container;
to
#ViewChild('container', { read: ViewContainerRef }) container: ViewContainerRef