Project Components and Databinding
This commit is contained in:
parent
776ad68f87
commit
37754150e6
@ -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">
|
||||||
|
@ -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!');
|
|
||||||
});
|
|
||||||
});
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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]
|
||||||
|
@ -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>
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -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">
|
||||||
|
@ -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() { }
|
||||||
|
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
<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>
|
||||||
</div>
|
</div>
|
||||||
<span class="pull-right">
|
<span class="pull-right">
|
||||||
<img
|
<img
|
||||||
[src]="recipe.imagePath"
|
[src]="recipe.imagePath"
|
||||||
alt="{{ recipe.name }}"
|
alt="{{ recipe.name }}"
|
||||||
class="img-responsive"
|
class="img-responsive"
|
||||||
style="max-height: 50px;">
|
style="max-height: 50px;">
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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() { }
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -18,4 +18,7 @@ export class ShoppingListComponent implements OnInit {
|
|||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onIngredientAdded(ingredient: Ingredient) {
|
||||||
|
this.ingredients.push(ingredient);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user