ng2 [disabled]="!myInput.value" doesnt work correctly - javascript

I'm building a standard angular2 app(more specific a todo app). I also added #Ngrx/store.
The first time I load the page, the button is disabled, but when I enter some value in the input box, the button needs to be enabled, but it stays disabled...
app/app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
template: `
<h1>Hello {{name}}</h1>
<div>
<add-todo></add-todo>
</div>`,
})
export class AppComponent { name = 'Angular'; }
app/components/add-todo/add-todo.component.ts
import { Component, ViewChild, ElementRef } from '#angular/core';
#Component({
moduleId: module.id,
selector: 'add-todo',
template: `
Create new todo
<input #myInput />
<button (click)="addTodo()" [disabled]="!myInput.value">Add</button>`
})
export class AddTodoComponent {
#ViewChild('myInput') input: ElementRef;
constructor() {}
addTodo(): void {
alert(this.input.nativeElement.value);
}
}

From the documentation https://angular.io/docs/ts/latest/guide/forms.html Track the change state and validity of form controls using ngModel...
Update your code to use ngModel and it should work as expected
import { Component, ViewChild, ElementRef } from '#angular/core';
#Component({
moduleId: module.id,
selector: 'add-todo',
template: `
Create new todo
<input #myInput [(ngModel)]="inputFieldValue" />
<button (click)="addTodo()" [disabled]="!myInput.value">Add</button>`
})
export class AddTodoComponent {
#ViewChild('myInput') input: ElementRef;
public inputFieldValue:string = '';
constructor() {}
addTodo(): void {
alert(this.input.nativeElement.value);
}
}

What if you do this way:
import {Component} from '#angular/core';
#Component({
selector: 'add-todo',
template: `
Create new todo
<input #todoTitleInput [(ngModel)]="todoTitle"/>
<button (click)="addTodo(todoTitleInput.value)" [disabled]="!todoTitle">Add</button>
`,
})
export class AddTodoComponent {
addTodo(title: string): void {
alert(title);
}
}

Related

Angular - How to invoke function from parent to child component

I have this situation: A parent component structured in this way:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-parent',
templateUrl: './parent.component.html',
styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
with this html (parent has an ng-content):
<div>
<ng-content></ng-content>
<button>Click to say Hello!!!</button>
</div>
and a child component like this:
import { Component, OnInit } from "#angular/core";
#Component({
selector: "app-child",
templateUrl: "./child.component.html",
styleUrls: ["./child.component.css"]
})
export class ChildComponent implements OnInit {
onSubmit() {
alert("hello");
}
constructor() {}
ngOnInit() {}
}
with this html:
<div>I'm child component</div>
From the parent component I want to click inside button to invoke onSubmit child function...is this possible?
<app-parent>
<app-child>
</app-child>
</app-parent>
This is a sample; I'm creating a modal that has default buttons: "CANCEL" and "SUCCESS". On the success button I need to invoke one function declared into the childrenComponent.
This is the stackblitz example: https://stackblitz.com/edit/angular-ivy-vuctg4
You can access like that
app.component.html
<hello name="{{ name }}"></hello>
<app-parent (clickActionCB)="clickActionCB($event)">
<app-child></app-child>
</app-parent>
app.component.ts
import { Component, VERSION, ViewChild } from "#angular/core";
import { ChildComponent } from "./child/child.component";
#Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
name = "Angular " + VERSION.major;
#ViewChild(ChildComponent) childRef: ChildComponent;
clickActionCB(eventData) {
this.childRef.onSubmit() ;
}
}
parent.component.ts
import { Component, EventEmitter, OnInit, Output } from "#angular/core";
#Component({
selector: "app-parent",
templateUrl: "./parent.component.html",
styleUrls: ["./parent.component.css"]
})
export class ParentComponent implements OnInit {
constructor() {}
ngOnInit() {}
#Output() clickActionCB = new EventEmitter<string>();
clickAction() {
this.clickActionCB.emit();
}
}
parent.component.html
<div>
<ng-content></ng-content>
<button (click)="clickAction()">Click to say Hello!!!</button>
</div>
Live stackblitz URL
child.component.ts
import { Component, OnInit } from "#angular/core";
#Component({
selector: "app-child",
template: `
<div>I'm child component</div>
`
})
export class ChildComponent implements OnInit {
onSubmit() {
alert("hello");
}
constructor() {}
ngOnInit() {}
}
parent.component.ts
import { ChildComponent } from "../child/child.component";
#Component({
selector: "app-parent",
template: `
<div>
<ng-content></ng-content>
<button (click)="onClick()">Click to say Hello!!!</button>
</div>
`
})
export class ParentComponent implements OnInit {
#ContentChild(ChildComponent) childRef: ChildComponent;
constructor() {}
ngOnInit() {}
onClick() {
this.childRef.onSubmit();
}
}
https://stackblitz.com/edit/angular-ivy-mteusj?file=src%2Fapp%2Fparent%2Fparent.component.ts

How to update other component html text value

This is my app.component.html source code:
<split-flap></split-flap>
<button (click)="flip('+')">+</button><button (click)="flip('-')">-</button>
This is my app.component.ts source code:
import { Component } from '#angular/core';
import { SplitFlapComponent } from './split-flap/split-flap.component';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers:[SplitFlapComponent]
})
export class AppComponent {
constructor(private splitFlapComponent: SplitFlapComponent)
{
}
flip(flag)
{
console.log(flag);
this.splitFlapComponent.title=flag;
}
}
This is my split-flap.component.ts:
import { Component, OnInit, Input, Output } from '#angular/core';
#Component({
selector: 'split-flap',
templateUrl: './split-flap.component.html',
styleUrls: ['./split-flap.component.css']
})
export class SplitFlapComponent implements OnInit {
title: string;
constructor() {
this.title = 'split-flap works1!';
}
ngOnInit() {
}
}
This is my split-flap.component.html:
<p>{{title}}</p>
My app.component.html has two buttons, both of them pass a sign to split-flap.component, would you tell me how can I the update split-flap.component.html content? Because most of the examples for input box only, I cannot find an example for <p>.
Try like this:
Solution 1 : #Input()
app.component.html
<split-flap [title]="title"></split-flap>
app.component.ts
title: string;
constructor() {
this.title = 'split-flap works1!';
}
flip(flag)
{
console.log(flag);
this.title=flag;
}
split-flap.component.ts:
#Input() title: string
Solution 2 : ViewChild()
app.component.html
<split-flap #child ></split-flap>
app.component.ts
#ViewChild('child') child: SplitFlapComponent ;
flip(flag)
{
console.log(flag);
this.child.title=flag;
}

Angular - How do I detect form events from inside a directive when they are initiated in component.ts file?

If I have a component with a form input and I want to detect the two statements in the OnInit block as events inside my directive, what is the correct way to do this? I have had luck with 'input' and 'ngModelChange', but none of the events I try to listen to catch the patchValue() method for model driven forms or the straight assignment for template driven forms (even though it reflects in the DOM).
Here is my Component:
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormControl } from '#angular/forms'
#Component({
selector: 'my-app',
template:
`
<h5>Model form input</h5>
<form [formGroup]="inputForm">
<input patchable-input formControlName="input" />
</form>
<h5>Template form input</h5>
<input patchable-input [(ngModel)]="input" />
`
})
export class AppComponent implements OnInit {
inputForm = new FormGroup({
input: new FormControl('')
})
input = '';
ngOnInit() {
this.inputForm.patchValue({
input: 'testing patch'
})
this.input = 'testing override'
}
}
Here is my Directive:
import { Directive, HostListener } from '#angular/core';
#Directive({
selector: '[patchable-input]'
})
export class PatchableInputDirective {
#HostListener('ngModelChange', ['$event']) ngOnChanges($event) {
console.log($event);
}
}
and a minimal reproduction in StackBlitz (watch the console)
You have to implement AfterViewInit instead of OnInit. The reason for that is at this point in the life cycle your directive has been initialized and has subscribed to the ngModelChange event via the #HostListener decorator.
See also the Angular Life Cycle Hooks documentation.
stackblitz
import { Component, AfterViewInit } from '#angular/core';
import { FormGroup, FormControl } from '#angular/forms'
#Component({
selector: 'my-app',
template:
`
<h5>Model form input</h5>
<form [formGroup]="inputForm">
<input patchable-input formControlName="input" />
</form>
<h5>Template form input</h5>
<input patchable-input [(ngModel)]="input" />
`
})
export class AppComponent implements AfterViewInit {
inputForm = new FormGroup({
input: new FormControl('')
})
input = '';
ngAfterViewInit() {
this.inputForm.patchValue({
input: 'testing patch'
})
}
}

html wont render from inside angular 2 component

I'm using a service to dynamically change the content in my header depending on the page I'm on, however when I put HTML in my component it doesn't render in the browser (see example below)
home.component.ts
import { Component, OnInit } from '#angular/core';
import { HeaderTitleService } from '../../services/headerTitle.service';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
constructor(
private headerTitleService: HeaderTitleService
) { }
ngOnInit() {
this.headerTitleService.setTitle(`
We strive to create things
<br> that are engaging, progressive
<br> & above all
<span class="highlight">
<em>innovative.</em>
</span>
`);
}
}
header.component.ts
import { Component, OnInit } from '#angular/core';
import { HeaderTitleService } from '../../../services/headerTitle.service'
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {
title: any;
constructor(
private headerTitleService: HeaderTitleService
) { }
ngOnInit() {
this.headerTitleService.title.subscribe(updatedTitle => {
this.title = updatedTitle;
});
}
}
header.component.html
<h1>{{title}}</h1>
so Im trying to set the title to be a string that has html tags in it that I want to be rendered but what happens is the whole thing comes out as a string instead of how it would look like it I had put it in my home.component.html.
Is there a way I can do this??
You can set the [innerHtml] property
<h1 [innerHtml]="title"></h1>
Example

Changing angular2 component model after changing element value with javascript or jquery

In my script I change value of an element with jquery(same with javascript), but model connected with this element was not changed. here is this element:
<input type="text" class="form-control" id="username" placeholder="Username" [(ngModel)]="user.username">
When I change value manually then model gets updated aswell. What should it be?
Thanks
Se plunker
Here an example:
Parent Component:
import { Comp1Component } from './../comp1/comp1.component';
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-comp-parent',
template:`
<p>ngModel: {{sharedVarParent}}</p>
<app-comp1 [comp1]="sharedVarParent" (sharedVarChange)="onChange($event)"></app-comp1>
<hr />
<app-comp2 [comp2]="sharedVarParent" (sharedVarChange)="onChange($event)"></app-comp2>
`
})
export class CompParentComponent implements OnInit {
sharedVarParent ='Initial';
onChange(ev){
this.sharedVarParent = ev;
}
}
COmp1:
import { Component, OnInit, Input, Output,EventEmitter } from '#angular/core';
#Component({
selector: 'app-comp1',
template:`
<input type="text" id="username" placeholder="{{comp1}}" [ngModel]="comp1" (ngModelChange)="change($event)">
<div>{{comp1}}</div>`
})
export class Comp1Component implements OnInit {
#Input() comp1;
#Output() sharedVarChange = new EventEmitter();
change(newValue) {
this.comp1 = newValue;
this.sharedVarChange.emit(newValue);
}
}
Comp2
import { Component, OnInit, Input, Output,EventEmitter } from '#angular/core';
#Component({
selector: 'app-comp2',
template:`
<input type="text" id="username" placeholder="{{comp2}}" [ngModel]="comp2" (ngModelChange)="change($event)">
<div>{{comp2}}</div>
`
})
export class Comp2Component implements OnInit {
#Input() comp2;
#Output() sharedVarChange = new EventEmitter();
change(newValue) {
this.comp2 = newValue;
this.sharedVarChange.emit(newValue);
}
}

Categories

Resources