Project Components and Databinding

This commit is contained in:
francesco 2021-12-14 12:57:13 +01:00
parent 776ad68f87
commit 37754150e6
18 changed files with 98 additions and 71 deletions

View File

@ -1,4 +1,4 @@
<app-header (featureSelected)="onNavgate($event)"></app-header> <app-header (featureSelected)="onNavigate($event)"></app-header>
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">

View File

@ -1,31 +0,0 @@
import { TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
});
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it(`should have as title 'project'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('project');
});
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('.content span')?.textContent).toContain('project app is running!');
});
});

View File

@ -6,10 +6,9 @@ import { Component } from '@angular/core';
styleUrls: ['./app.component.css'] styleUrls: ['./app.component.css']
}) })
export class AppComponent { export class AppComponent {
title = 'project';
loadedFeature = 'recipe'; loadedFeature = 'recipe';
onNavgate(feature: string) { onNavigate(feature: string) {
this.loadedFeature = feature; this.loadedFeature = feature;
} }
} }

View File

@ -1,6 +1,6 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { HeaderComponent } from './header/header.component'; import { HeaderComponent } from './header/header.component';
import { RecipesComponent } from './recipes/recipes.component'; import { RecipesComponent } from './recipes/recipes.component';
@ -22,7 +22,8 @@ import { ShoppingEditComponent } from './shopping-list/shopping-edit/shopping-ed
ShoppingEditComponent ShoppingEditComponent
], ],
imports: [ imports: [
BrowserModule BrowserModule,
FormsModule,
], ],
providers: [], providers: [],
bootstrap: [AppComponent] bootstrap: [AppComponent]

View File

@ -5,15 +5,15 @@
</div> </div>
<div class="navbar-default"> <div class="navbar-default">
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li><a href="#" (click)="onSelect('recipe')">Recipe</a></li> <li><a href="#" (click)="onSelect('recipe')">Recipes</a></li>
<li><a href="#" (click)="onSelect('shopping-list')">Shopping List</a></li> <li><a href="#" (click)="onSelect('shopping-list')">Shopping List</a></li>
</ul> </ul>
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
<li class="dropdown"> <li class="dropdown">
<a href="#" class="dropdown-toggle" role="button">Manage<span Class="caret"></span></a> <a href="#" class="dropdown-toggle" role="button">Manage <span class="caret"></span></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a>/li>href="#">Saving data</a></li> <li><a href="#">Save Data</a></li>
<li><a href="#">Fetching data</a></li> <li><a href="#">Fetch Data</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>

View File

@ -2,8 +2,7 @@ import { Component, EventEmitter, Output } from '@angular/core';
@Component({ @Component({
selector: 'app-header', selector: 'app-header',
templateUrl: './header.component.html', templateUrl: './header.component.html'
styleUrls: ['./header.component.css']
}) })
export class HeaderComponent { export class HeaderComponent {
@Output() featureSelected = new EventEmitter<string>(); @Output() featureSelected = new EventEmitter<string>();
@ -11,5 +10,4 @@ export class HeaderComponent {
onSelect(feature: string) { onSelect(feature: string) {
this.featureSelected.emit(feature); this.featureSelected.emit(feature);
} }
} }

View File

@ -1,11 +1,15 @@
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
<img src="" alt="" class="img-responsive"> <img
[src]="recipe.imagePath"
alt="{{ recipe.name }}"
class="img-responsive"
style="max-height: 300px;">
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
<h1>Recipe Name</h1> <h1>{{ recipe.name }}</h1>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
@ -26,7 +30,7 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
Description {{ recipe.description }}
</div> </div>
</div> </div>
<div class="row"> <div class="row">

View File

@ -1,4 +1,6 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit, Input } from '@angular/core';
import { Recipe } from '../recipe.model';
@Component({ @Component({
selector: 'app-recipe-detail', selector: 'app-recipe-detail',
@ -6,6 +8,7 @@ import { Component, OnInit } from '@angular/core';
styleUrls: ['./recipe-detail.component.css'] styleUrls: ['./recipe-detail.component.css']
}) })
export class RecipeDetailComponent implements OnInit { export class RecipeDetailComponent implements OnInit {
@Input() recipe: Recipe;
constructor() { } constructor() { }

View File

@ -1,6 +1,7 @@
<a <a
href="#" href="#"
class="list-group-item clearfix"> class="list-group-item clearfix"
(click)="onSelected()">
<div class="pull-left"> <div class="pull-left">
<h4 class="list-group-item-heading">{{ recipe.name }}</h4> <h4 class="list-group-item-heading">{{ recipe.name }}</h4>
<p class="list-group-item-text">{{ recipe.description }}</p> <p class="list-group-item-text">{{ recipe.description }}</p>

View File

@ -1,4 +1,5 @@
import { Component, Input, OnInit } from '@angular/core'; import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core';
import { Recipe } from '../../recipe.model'; import { Recipe } from '../../recipe.model';
@Component({ @Component({
@ -8,10 +9,15 @@ import { Recipe } from '../../recipe.model';
}) })
export class RecipeItemComponent implements OnInit { export class RecipeItemComponent implements OnInit {
@Input() recipe: Recipe; @Input() recipe: Recipe;
@Output() recipeSelected = new EventEmitter<void>();
constructor() { } constructor() { }
ngOnInit() { ngOnInit() {
} }
onSelected() {
this.recipeSelected.emit();
}
} }

View File

@ -7,8 +7,9 @@
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
<app-recipe-item <app-recipe-item
*ngFor="let recipeElement of recipes" *ngFor="let recipeEl of recipes"
[recipe]="recipeElement"></app-recipe-item> [recipe]="recipeEl"
(recipeSelected)="onRecipeSelected(recipeEl)"></app-recipe-item>
</div> </div>
</div> </div>

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit, EventEmitter, Output } from '@angular/core';
import { Recipe } from '../recipe.model'; import { Recipe } from '../recipe.model';
@ -8,9 +8,10 @@ import { Recipe } from '../recipe.model';
styleUrls: ['./recipe-list.component.css'] styleUrls: ['./recipe-list.component.css']
}) })
export class RecipeListComponent implements OnInit { export class RecipeListComponent implements OnInit {
@Output() recipeWasSelected = new EventEmitter<Recipe>();
recipes: Recipe[] = [ recipes: Recipe[] = [
new Recipe('A Test Recipe', 'This is simply a test', 'https://upload.wikimedia.org/wikipedia/commons/1/15/Recipe_logo.jpeg'), new Recipe('A Test Recipe', 'This is simply a test', 'https://upload.wikimedia.org/wikipedia/commons/1/15/Recipe_logo.jpeg'),
new Recipe('A Test Recipe', 'This is simply a test', 'https://upload.wikimedia.org/wikipedia/commons/1/15/Recipe_logo.jpeg') new Recipe('Another Test Recipe', 'This is simply a test', 'https://upload.wikimedia.org/wikipedia/commons/1/15/Recipe_logo.jpeg')
]; ];
constructor() { } constructor() { }
@ -18,4 +19,8 @@ export class RecipeListComponent implements OnInit {
ngOnInit() { ngOnInit() {
} }
onRecipeSelected(recipe: Recipe) {
this.recipeWasSelected.emit(recipe);
}
} }

View File

@ -1,8 +1,14 @@
<div class="row"> <div class="row">
<div class="col-md-5"> <div class="col-md-5">
<app-recipe-list></app-recipe-list> <app-recipe-list
(recipeWasSelected)="selectedRecipe = $event"></app-recipe-list>
</div> </div>
<div class="col-md-7"> <div class="col-md-7">
<app-recipe-detail></app-recipe-detail> <app-recipe-detail
*ngIf="selectedRecipe; else infoText"
[recipe]="selectedRecipe"></app-recipe-detail>
<ng-template #infoText>
<p>Please select a Recipe!</p>
</ng-template>
</div> </div>
</div> </div>

View File

@ -1,11 +1,14 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Recipe } from './recipe.model';
@Component({ @Component({
selector: 'app-recipes', selector: 'app-recipes',
templateUrl: './recipes.component.html', templateUrl: './recipes.component.html',
styleUrls: ['./recipes.component.css'] styleUrls: ['./recipes.component.css']
}) })
export class RecipesComponent implements OnInit { export class RecipesComponent implements OnInit {
selectedRecipe: Recipe;
constructor() { } constructor() { }

View File

@ -4,16 +4,24 @@
<div class="row"> <div class="row">
<div class="col-sm-5 form-group"> <div class="col-sm-5 form-group">
<label for="name">Name</label> <label for="name">Name</label>
<input type="text" id="name" class="form-control"> <input
type="text"
id="name"
class="form-control"
#nameInput>
</div> </div>
<div class="col-sm-2 form-group"> <div class="col-sm-2 form-group">
<label for="amount">Amount</label> <label for="amount">Amount</label>
<input type="number" id="amount" class="form-control"> <input
type="number"
id="amount"
class="form-control"
#amountInput>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
<button class="btn btn-success" type="submit">Add</button> <button class="btn btn-success" type="submit" (click)="onAddItem()">Add</button>
<button class="btn btn-danger" type="button">Delete</button> <button class="btn btn-danger" type="button">Delete</button>
<button class="btn btn-primary" type="button">Clear</button> <button class="btn btn-primary" type="button">Clear</button>
</div> </div>

View File

@ -1,4 +1,13 @@
import { Component, OnInit } from '@angular/core'; import {
Component,
OnInit,
ElementRef,
ViewChild,
EventEmitter,
Output
} from '@angular/core';
import { Ingredient } from '../../shared/ingredient.model';
@Component({ @Component({
selector: 'app-shopping-edit', selector: 'app-shopping-edit',
@ -6,10 +15,20 @@ import { Component, OnInit } from '@angular/core';
styleUrls: ['./shopping-edit.component.css'] styleUrls: ['./shopping-edit.component.css']
}) })
export class ShoppingEditComponent implements OnInit { export class ShoppingEditComponent implements OnInit {
@ViewChild('nameInput', { static: false }) nameInputRef: ElementRef;
@ViewChild('amountInput', { static: false }) amountInputRef: ElementRef;
@Output() ingredientAdded = new EventEmitter<Ingredient>();
constructor() { } constructor() { }
ngOnInit() { ngOnInit() {
} }
onAddItem() {
const ingName = this.nameInputRef.nativeElement.value;
const ingAmount = this.amountInputRef.nativeElement.value;
const newIngredient = new Ingredient(ingName, ingAmount);
this.ingredientAdded.emit(newIngredient);
}
} }

View File

@ -1,6 +1,7 @@
<div class="row"> <div class="row">
<div class="col-xs-10"> <div class="col-xs-10">
<app-shopping-edit></app-shopping-edit> <app-shopping-edit
(ingredientAdded)="onIngredientAdded($event)"></app-shopping-edit>
<hr> <hr>
<ul class="list-group"> <ul class="list-group">
<a <a

View File

@ -18,4 +18,7 @@ export class ShoppingListComponent implements OnInit {
ngOnInit() { ngOnInit() {
} }
onIngredientAdded(ingredient: Ingredient) {
this.ingredients.push(ingredient);
}
} }