From 1e496e85bf88ae214a12356fe5b4111d4601055b Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Fri, 11 Oct 2013 15:18:31 -0700 Subject: [PATCH 01/21] Hello World Angular Dart --- Chapter_01/index.html | 14 ++++++++++++++ Chapter_01/main.dart | 5 +++++ Chapter_01/pubspec.yaml | 10 ++++++++++ 3 files changed, 29 insertions(+) create mode 100644 Chapter_01/index.html create mode 100644 Chapter_01/main.dart create mode 100644 Chapter_01/pubspec.yaml diff --git a/Chapter_01/index.html b/Chapter_01/index.html new file mode 100644 index 0000000..880e5f2 --- /dev/null +++ b/Chapter_01/index.html @@ -0,0 +1,14 @@ + + + + Hello, World! + + + +

Hello {{name}}!

+ name: + + + + + diff --git a/Chapter_01/main.dart b/Chapter_01/main.dart new file mode 100644 index 0000000..630aed6 --- /dev/null +++ b/Chapter_01/main.dart @@ -0,0 +1,5 @@ +import 'package:angular/angular.dart'; + +main() { + bootstrapAngular([new AngularModule()]); +} diff --git a/Chapter_01/pubspec.yaml b/Chapter_01/pubspec.yaml new file mode 100644 index 0000000..c5b05c1 --- /dev/null +++ b/Chapter_01/pubspec.yaml @@ -0,0 +1,10 @@ +name: angular_dart_demo +version: 0.0.1 +dependencies: + angular: + git: https://github.com/angular/angular.dart.git + # git: https://github.com/mhevery/angular.dart.git + + browser: any + js: any + unittest: any From d08d8ac12eca6d59dbed95560ef8258e1d6cafbf Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Fri, 11 Oct 2013 15:53:24 -0700 Subject: [PATCH 02/21] First version of Recipe Book Angular Dart app --- Chapter_02/index.html | 34 ++++++++++++++++++++ Chapter_02/main.dart | 69 +++++++++++++++++++++++++++++++++++++++++ Chapter_02/pubspec.yaml | 10 ++++++ 3 files changed, 113 insertions(+) create mode 100644 Chapter_02/index.html create mode 100644 Chapter_02/main.dart create mode 100644 Chapter_02/pubspec.yaml diff --git a/Chapter_02/index.html b/Chapter_02/index.html new file mode 100644 index 0000000..5ea2499 --- /dev/null +++ b/Chapter_02/index.html @@ -0,0 +1,34 @@ + + + + Part Two - A Simple Recipe Catalog + + + + +
+

Choose a recipe to view

+
    +
  • {{recipe.name}}
  • +
+ +

Recipe Information

+
Name: {{ctrl.selectedRecipe.name}}
+
Category: {{ctrl.selectedRecipe.category}}
+
Rating: {{ctrl.selectedRecipe.rating}}
+
+
    +
  • + {{ingredient}} +
  • +
+
+
Directions: {{ctrl.selectedRecipe.directions}}
+
+ + + + + diff --git a/Chapter_02/main.dart b/Chapter_02/main.dart new file mode 100644 index 0000000..ca43d48 --- /dev/null +++ b/Chapter_02/main.dart @@ -0,0 +1,69 @@ +import 'package:angular/angular.dart'; + +/* Use the NgDirective annotation to indicate that this class is an + * Angular Directive. The compiler will instantiate the directive if + * it finds it in the DOM. + * + * The selector field defines the CSS selector that will trigger the + * directive. It can be any valid CSS selector which does not cross + * element boundaries. + * + * The publishAs field specifies that the directive instance should be + * assigned to the current scope under the name specified. + * + * The directive's public fields are available for data binding from the view. + * Similarly, the directive's public methods can be invoked from the view. + */ +@NgDirective( + selector: '[catalog-controller]', + publishAs: 'ctrl') +class CatalogController { + + List recipes = [ + new Recipe('My Appetizer','Appetizers', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 1), + new Recipe('My Salad','Salads', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 3), + new Recipe('My Soup','Soups', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 4), + new Recipe('My Main Dish','Main Dishes', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 2), + new Recipe('My Side Dish','Side Dishes', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 3), + new Recipe('My Awesome Dessert','Desserts', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 5), + new Recipe('My So-So Dessert','Desserts', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 3), + ]; + + Recipe selectedRecipe; + + void selectRecipe(Recipe recipe) { + selectedRecipe = recipe; + } + +} + +class Recipe { + String name; + String category; + List ingredients; + String directions; + int rating; + + Recipe(this.name, this.category, this.ingredients, this.directions, + this.rating); +} + +main() { + var module = new AngularModule() + ..type(CatalogController); + bootstrapAngular([module]); +} \ No newline at end of file diff --git a/Chapter_02/pubspec.yaml b/Chapter_02/pubspec.yaml new file mode 100644 index 0000000..c5b05c1 --- /dev/null +++ b/Chapter_02/pubspec.yaml @@ -0,0 +1,10 @@ +name: angular_dart_demo +version: 0.0.1 +dependencies: + angular: + git: https://github.com/angular/angular.dart.git + # git: https://github.com/mhevery/angular.dart.git + + browser: any + js: any + unittest: any From 854c6815f8198a4f0b669487e22d7a899362c43d Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Mon, 14 Oct 2013 09:24:16 -0700 Subject: [PATCH 03/21] Updating chapter 2 example code. --- Chapter_02/index.html | 4 +-- Chapter_02/main.dart | 59 +++++++++++++++++++++++-------------------- Chapter_02/style.css | 3 +++ 3 files changed, 36 insertions(+), 30 deletions(-) create mode 100644 Chapter_02/style.css diff --git a/Chapter_02/index.html b/Chapter_02/index.html index 5ea2499..a7656e8 100644 --- a/Chapter_02/index.html +++ b/Chapter_02/index.html @@ -2,11 +2,11 @@ Part Two - A Simple Recipe Catalog - + -
+

Choose a recipe to view

  • _loadData() { + return [ + new Recipe('My Appetizer','Appetizers', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 1), + new Recipe('My Salad','Salads', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 3), + new Recipe('My Soup','Soups', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 4), + new Recipe('My Main Dish','Main Dishes', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 2), + new Recipe('My Side Dish','Side Dishes', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 3), + new Recipe('My Awesome Dessert','Desserts', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 5), + new Recipe('My So-So Dessert','Desserts', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 3), + ]; +} + main() { var module = new AngularModule() - ..type(CatalogController); + ..type(RecipeBookController); bootstrapAngular([module]); -} \ No newline at end of file +} diff --git a/Chapter_02/style.css b/Chapter_02/style.css new file mode 100644 index 0000000..b77a62e --- /dev/null +++ b/Chapter_02/style.css @@ -0,0 +1,3 @@ +.pointer { + cursor: pointer; +} \ No newline at end of file From 02ec707bb0acab473b80b3210a78f209dc8914a8 Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Mon, 14 Oct 2013 11:09:34 -0700 Subject: [PATCH 04/21] rearranging some code --- Chapter_02/main.dart | 57 +++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/Chapter_02/main.dart b/Chapter_02/main.dart index 43155ee..cd32903 100644 --- a/Chapter_02/main.dart +++ b/Chapter_02/main.dart @@ -19,13 +19,42 @@ import 'package:angular/angular.dart'; publishAs: 'ctrl') class RecipeBookController { - List recipes = _loadData(); + List recipes; + RecipeBookController() { + recipes = _loadData(); + } Recipe selectedRecipe; void selectRecipe(Recipe recipe) { selectedRecipe = recipe; } + + List _loadData() { + return [ + new Recipe('My Appetizer','Appetizers', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 1), + new Recipe('My Salad','Salads', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 3), + new Recipe('My Soup','Soups', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 4), + new Recipe('My Main Dish','Main Dishes', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 2), + new Recipe('My Side Dish','Side Dishes', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 3), + new Recipe('My Awesome Dessert','Desserts', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 5), + new Recipe('My So-So Dessert','Desserts', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 3), + ]; + } } class Recipe { @@ -39,32 +68,6 @@ class Recipe { this.rating); } -List _loadData() { - return [ - new Recipe('My Appetizer','Appetizers', - ["Ingredient 1", "Ingredient 2"], - "Some Directions", 1), - new Recipe('My Salad','Salads', - ["Ingredient 1", "Ingredient 2"], - "Some Directions", 3), - new Recipe('My Soup','Soups', - ["Ingredient 1", "Ingredient 2"], - "Some Directions", 4), - new Recipe('My Main Dish','Main Dishes', - ["Ingredient 1", "Ingredient 2"], - "Some Directions", 2), - new Recipe('My Side Dish','Side Dishes', - ["Ingredient 1", "Ingredient 2"], - "Some Directions", 3), - new Recipe('My Awesome Dessert','Desserts', - ["Ingredient 1", "Ingredient 2"], - "Some Directions", 5), - new Recipe('My So-So Dessert','Desserts', - ["Ingredient 1", "Ingredient 2"], - "Some Directions", 3), - ]; -} - main() { var module = new AngularModule() ..type(RecipeBookController); From 137b37d5c760801eebabf3de8b878c34309bd08b Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Mon, 14 Oct 2013 16:03:08 -0700 Subject: [PATCH 05/21] fixing typo --- Chapter_02/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chapter_02/index.html b/Chapter_02/index.html index a7656e8..474692d 100644 --- a/Chapter_02/index.html +++ b/Chapter_02/index.html @@ -1,7 +1,7 @@ - Part Two - A Simple Recipe Catalog + Chapter Two - A Simple Recipe Book From c1deb88aba8f4c52ba597adcdad5386edc48fe0a Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Mon, 14 Oct 2013 16:03:30 -0700 Subject: [PATCH 06/21] first pass at chapter 3 --- Chapter_03/index.html | 41 +++++++++++ Chapter_03/main.dart | 114 +++++++++++++++++++++++++++++++ Chapter_03/pubspec.yaml | 10 +++ Chapter_03/rating_component.css | 10 +++ Chapter_03/rating_component.html | 4 ++ Chapter_03/style.css | 7 ++ 6 files changed, 186 insertions(+) create mode 100644 Chapter_03/index.html create mode 100644 Chapter_03/main.dart create mode 100644 Chapter_03/pubspec.yaml create mode 100644 Chapter_03/rating_component.css create mode 100644 Chapter_03/rating_component.html create mode 100644 Chapter_03/style.css diff --git a/Chapter_03/index.html b/Chapter_03/index.html new file mode 100644 index 0000000..7cb423f --- /dev/null +++ b/Chapter_03/index.html @@ -0,0 +1,41 @@ + + + + Chapter Three - A Simple Recipe Book + + + + +
    +

    Choose a recipe to view

    +
      +
    • + + {{recipe.name}} +
    • +
    + +

    Recipe Information

    +
    +
    Name: {{ctrl.selectedRecipe.name}}
    +
    Category: {{ctrl.selectedRecipe.category}}
    +
    Rating: + +
    +
    +
      +
    • + {{ingredient}} +
    • +
    +
    +
    Directions: {{ctrl.selectedRecipe.directions}}
    +
    +
    + + + + + diff --git a/Chapter_03/main.dart b/Chapter_03/main.dart new file mode 100644 index 0000000..99b72e1 --- /dev/null +++ b/Chapter_03/main.dart @@ -0,0 +1,114 @@ +import 'package:angular/angular.dart'; +import 'package:di/di.dart'; + +@NgDirective( + selector: '[recipe-book]', + publishAs: 'ctrl') +class RecipeBookController { + + List recipes; + + RecipeBookController() { + recipes = _loadData(); + } + + Recipe selectedRecipe; + + void selectRecipe(Recipe recipe) { + selectedRecipe = recipe; + } + + List _loadData() { + return [ + new Recipe('My Appetizer','Appetizers', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 1), + new Recipe('My Salad','Salads', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 3), + new Recipe('My Soup','Soups', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 4), + new Recipe('My Main Dish','Main Dishes', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 2), + new Recipe('My Side Dish','Side Dishes', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 3), + new Recipe('My Awesome Dessert','Desserts', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 5), + new Recipe('My So-So Dessert','Desserts', + ["Ingredient 1", "Ingredient 2"], + "Some Directions", 3), + ]; + } +} + +@NgComponent( + selector: 'rating', + templateUrl: 'rating_component.html', + cssUrl: 'rating_component.css', + publishAs: 'ctrl', + map: const { + 'max': '@.max' + } +) +class RatingComponent { + final NgModel ngModel; + + String _starOnChar = "\u2605"; + String _starOffChar = "\u2606"; + String _starOnClass = "star-on"; + String _starOffClass = "star-off"; + + List stars = []; + + get rating => ngModel.viewValue; + set rating(value) => ngModel.viewValue = value; + + set max(String value) { + stars = []; + var count = int.parse(value); + for(var i=1; i <= count; i++) { + stars.add(i); + } + } + + RatingComponent(NgModel this.ngModel); + + String starClass(int star) { + return star > rating ? _starOffClass : _starOnClass; + } + + String starChar(int star) { + return star > rating ? _starOffChar : _starOnChar; + } + + void clickStar(int star) { + if (star == 1 && rating == 1) { + rating = 0; + } else { + rating = star; + } + } +} + +class Recipe { + String name; + String category; + List ingredients; + String directions; + int rating; + + Recipe(this.name, this.category, this.ingredients, this.directions, + this.rating); +} + +main() { + var module = new AngularModule() + ..type(RecipeBookController) + ..type(RatingComponent); + + bootstrapAngular([module]); +} \ No newline at end of file diff --git a/Chapter_03/pubspec.yaml b/Chapter_03/pubspec.yaml new file mode 100644 index 0000000..c5b05c1 --- /dev/null +++ b/Chapter_03/pubspec.yaml @@ -0,0 +1,10 @@ +name: angular_dart_demo +version: 0.0.1 +dependencies: + angular: + git: https://github.com/angular/angular.dart.git + # git: https://github.com/mhevery/angular.dart.git + + browser: any + js: any + unittest: any diff --git a/Chapter_03/rating_component.css b/Chapter_03/rating_component.css new file mode 100644 index 0000000..050d544 --- /dev/null +++ b/Chapter_03/rating_component.css @@ -0,0 +1,10 @@ +.star-off { + color: #6E6E6E; +} +.star-on { + color: #FACC2E; +} +span { + letter-spacing: -2px; + cursor: pointer; +} \ No newline at end of file diff --git a/Chapter_03/rating_component.html b/Chapter_03/rating_component.html new file mode 100644 index 0000000..ce6d913 --- /dev/null +++ b/Chapter_03/rating_component.html @@ -0,0 +1,4 @@ + + {{ctrl.starChar(star)}} + diff --git a/Chapter_03/style.css b/Chapter_03/style.css new file mode 100644 index 0000000..bb46564 --- /dev/null +++ b/Chapter_03/style.css @@ -0,0 +1,7 @@ +.pointer { + cursor: pointer; +} + +.extra-space { + padding-left: 10px; +} \ No newline at end of file From b241f33a656025b1f5262d81538a7d89e4a99a3c Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Wed, 16 Oct 2013 11:27:50 -0700 Subject: [PATCH 07/21] separate rating component into its own dart file. misc code clean up. --- Chapter_02/index.html | 4 +-- Chapter_03/index.html | 18 +++++----- Chapter_03/main.dart | 52 ++--------------------------- Chapter_03/rating_component.css | 2 +- Chapter_03/rating_component.dart | 57 ++++++++++++++++++++++++++++++++ Chapter_03/rating_component.html | 11 +++--- Chapter_03/style.css | 2 +- 7 files changed, 80 insertions(+), 66 deletions(-) create mode 100644 Chapter_03/rating_component.dart diff --git a/Chapter_02/index.html b/Chapter_02/index.html index 474692d..63b349d 100644 --- a/Chapter_02/index.html +++ b/Chapter_02/index.html @@ -7,14 +7,14 @@
    -

    Choose a recipe to view

    +

    Recipe List

    • {{recipe.name}}
    -

    Recipe Information

    +

    Recipe Details

    Name: {{ctrl.selectedRecipe.name}}
    Category: {{ctrl.selectedRecipe.category}}
    Rating: {{ctrl.selectedRecipe.rating}}
    diff --git a/Chapter_03/index.html b/Chapter_03/index.html index 7cb423f..9cfc7d6 100644 --- a/Chapter_03/index.html +++ b/Chapter_03/index.html @@ -6,23 +6,23 @@ -
    -

    Choose a recipe to view

    +
    +

    Recipe List

    • - - {{recipe.name}} + ng-repeat="recipe in ctrl.recipes"> + + {{recipe.name}}
    - -

    Recipe Information

    + +

    Recipe Details

    Name: {{ctrl.selectedRecipe.name}}
    Category: {{ctrl.selectedRecipe.category}}
    Rating: - +
      diff --git a/Chapter_03/main.dart b/Chapter_03/main.dart index 99b72e1..4971eb3 100644 --- a/Chapter_03/main.dart +++ b/Chapter_03/main.dart @@ -1,5 +1,6 @@ import 'package:angular/angular.dart'; import 'package:di/di.dart'; +import 'rating_component.dart'; @NgDirective( selector: '[recipe-book]', @@ -18,6 +19,8 @@ class RecipeBookController { selectedRecipe = recipe; } + String foo = 'foo'; + List _loadData() { return [ new Recipe('My Appetizer','Appetizers', @@ -45,55 +48,6 @@ class RecipeBookController { } } -@NgComponent( - selector: 'rating', - templateUrl: 'rating_component.html', - cssUrl: 'rating_component.css', - publishAs: 'ctrl', - map: const { - 'max': '@.max' - } -) -class RatingComponent { - final NgModel ngModel; - - String _starOnChar = "\u2605"; - String _starOffChar = "\u2606"; - String _starOnClass = "star-on"; - String _starOffClass = "star-off"; - - List stars = []; - - get rating => ngModel.viewValue; - set rating(value) => ngModel.viewValue = value; - - set max(String value) { - stars = []; - var count = int.parse(value); - for(var i=1; i <= count; i++) { - stars.add(i); - } - } - - RatingComponent(NgModel this.ngModel); - - String starClass(int star) { - return star > rating ? _starOffClass : _starOnClass; - } - - String starChar(int star) { - return star > rating ? _starOffChar : _starOnChar; - } - - void clickStar(int star) { - if (star == 1 && rating == 1) { - rating = 0; - } else { - rating = star; - } - } -} - class Recipe { String name; String category; diff --git a/Chapter_03/rating_component.css b/Chapter_03/rating_component.css index 050d544..a153cd7 100644 --- a/Chapter_03/rating_component.css +++ b/Chapter_03/rating_component.css @@ -4,7 +4,7 @@ .star-on { color: #FACC2E; } -span { +.stars { letter-spacing: -2px; cursor: pointer; } \ No newline at end of file diff --git a/Chapter_03/rating_component.dart b/Chapter_03/rating_component.dart new file mode 100644 index 0000000..ef42081 --- /dev/null +++ b/Chapter_03/rating_component.dart @@ -0,0 +1,57 @@ +import 'package:angular/angular.dart'; + +/* Use the NgComponent annotation to indicate that this class is an + * Angular Component. + * + * The selector field defines the CSS selector that will trigger the + * component. Typically, the CSS selector is an element name. + * + * TODO: adopt new map naming conventions as soon as they're ready. + * 'max': '@.max' + * will become + * 'max-rating': '@maxRating' + */ +@NgComponent( + selector: 'rating', + templateUrl: 'rating_component.html', + cssUrl: 'rating_component.css', + publishAs: 'ctrl', + map: const { + 'max': '@.max', + 'rating' : '=.rating' + } +) +class RatingComponent { + String _starOnChar = "\u2605"; + String _starOffChar = "\u2606"; + String _starOnClass = "star-on"; + String _starOffClass = "star-off"; + + List stars = []; + + int rating; + + set max(String value) { + stars = []; + var count = value == null ? 5 : int.parse(value); + for(var i=1; i <= count; i++) { + stars.add(i); + } + } + + String starClass(int star) { + return star > rating ? _starOffClass : _starOnClass; + } + + String starChar(int star) { + return star > rating ? _starOffChar : _starOnChar; + } + + void handleClick(int star) { + if (star == 1 && rating == 1) { + rating = 0; + } else { + rating = star; + } + } +} diff --git a/Chapter_03/rating_component.html b/Chapter_03/rating_component.html index ce6d913..7a8f89b 100644 --- a/Chapter_03/rating_component.html +++ b/Chapter_03/rating_component.html @@ -1,4 +1,7 @@ - - {{ctrl.starChar(star)}} - + + {{ctrl.starChar(star)}} + \ No newline at end of file diff --git a/Chapter_03/style.css b/Chapter_03/style.css index bb46564..e0cd81b 100644 --- a/Chapter_03/style.css +++ b/Chapter_03/style.css @@ -4,4 +4,4 @@ .extra-space { padding-left: 10px; -} \ No newline at end of file +} From 8c2a66358da4dc46b9dd2c5e3330f5e3cf7cc8da Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Wed, 16 Oct 2013 11:28:14 -0700 Subject: [PATCH 08/21] separate rating component into its own dart file. misc code clean up. --- Chapter_03/main.dart | 2 -- Chapter_03/rating_component.css | 2 +- Chapter_03/rating_component.dart | 29 +++++++++++++++++++++++++---- Chapter_03/rating_component.html | 2 +- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/Chapter_03/main.dart b/Chapter_03/main.dart index 4971eb3..61c9de7 100644 --- a/Chapter_03/main.dart +++ b/Chapter_03/main.dart @@ -19,8 +19,6 @@ class RecipeBookController { selectedRecipe = recipe; } - String foo = 'foo'; - List _loadData() { return [ new Recipe('My Appetizer','Appetizers', diff --git a/Chapter_03/rating_component.css b/Chapter_03/rating_component.css index a153cd7..114c9ae 100644 --- a/Chapter_03/rating_component.css +++ b/Chapter_03/rating_component.css @@ -7,4 +7,4 @@ .stars { letter-spacing: -2px; cursor: pointer; -} \ No newline at end of file +} diff --git a/Chapter_03/rating_component.dart b/Chapter_03/rating_component.dart index ef42081..b84df07 100644 --- a/Chapter_03/rating_component.dart +++ b/Chapter_03/rating_component.dart @@ -6,10 +6,31 @@ import 'package:angular/angular.dart'; * The selector field defines the CSS selector that will trigger the * component. Typically, the CSS selector is an element name. * + * The templateUrl field tells the component which HTML template to use + * for its view. + * + * The cssUrl field tells the component which CSS file to use. + * + * The publishAs field specifies that the component instance should be + * assigned to the current scope under the name specified. + * + * The map field publishes the list of attributes that can be set on + * the component. Users of this component will specify these attributes + * in the html tag that is used to create the component. For example: + * + * + * * TODO: adopt new map naming conventions as soon as they're ready. - * 'max': '@.max' - * will become - * 'max-rating': '@maxRating' + * OLD: + * 'max' : '@.max', + * 'rating' : '=.rating' + * NEW: + * 'max-rating' : '@maxRating', + * 'rating' : '=rating' + * + * The compnoent's public fields are available for data binding from the + * component's view. Similarly, the component's public methods can be + * invoked from the component's view. */ @NgComponent( selector: 'rating', @@ -17,7 +38,7 @@ import 'package:angular/angular.dart'; cssUrl: 'rating_component.css', publishAs: 'ctrl', map: const { - 'max': '@.max', + 'max' : '@.max', 'rating' : '=.rating' } ) diff --git a/Chapter_03/rating_component.html b/Chapter_03/rating_component.html index 7a8f89b..4d4c94e 100644 --- a/Chapter_03/rating_component.html +++ b/Chapter_03/rating_component.html @@ -4,4 +4,4 @@ ng-click="ctrl.handleClick(star)" ng-class="ctrl.starClass(star)"> {{ctrl.starChar(star)}} - \ No newline at end of file + From ceb9af16960742eb4b4f724ab73b44251a52075b Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Thu, 17 Oct 2013 16:30:24 -0700 Subject: [PATCH 09/21] Adding code for chapter 4 --- Chapter_04/index.html | 46 +++++++++++++++++++ Chapter_04/main.dart | 54 ++++++++++++++++++++++ Chapter_04/pubspec.yaml | 10 ++++ Chapter_04/rating_component.css | 10 ++++ Chapter_04/rating_component.dart | 78 ++++++++++++++++++++++++++++++++ Chapter_04/rating_component.html | 7 +++ Chapter_04/recipe.dart | 30 ++++++++++++ Chapter_04/recipes.json | 51 +++++++++++++++++++++ Chapter_04/style.css | 11 +++++ 9 files changed, 297 insertions(+) create mode 100644 Chapter_04/index.html create mode 100644 Chapter_04/main.dart create mode 100644 Chapter_04/pubspec.yaml create mode 100644 Chapter_04/rating_component.css create mode 100644 Chapter_04/rating_component.dart create mode 100644 Chapter_04/rating_component.html create mode 100644 Chapter_04/recipe.dart create mode 100644 Chapter_04/recipes.json create mode 100644 Chapter_04/style.css diff --git a/Chapter_04/index.html b/Chapter_04/index.html new file mode 100644 index 0000000..b71effb --- /dev/null +++ b/Chapter_04/index.html @@ -0,0 +1,46 @@ + + + + Chapter Four - A Simple Recipe Book + + + + +
      +

      Recipe List

      + + + + +
        +
      • + + {{recipe.name}} +
      • +
      + +

      Recipe Details

      +
      +
      Name: {{ctrl.selectedRecipe.name}}
      +
      Category: {{ctrl.selectedRecipe.category}}
      +
      Rating: + +
      +
      +
        +
      • + {{ingredient}} +
      • +
      +
      +
      Directions: {{ctrl.selectedRecipe.directions}}
      +
      +
      + + + + + diff --git a/Chapter_04/main.dart b/Chapter_04/main.dart new file mode 100644 index 0000000..9ada884 --- /dev/null +++ b/Chapter_04/main.dart @@ -0,0 +1,54 @@ +import 'package:angular/angular.dart'; +import 'package:di/di.dart'; +import 'rating_component.dart'; +import 'recipe.dart'; + +@NgFilter(name: 'searchfilter') +class SearchFilter { + call(value, filterString) { + if (value is List && filterString != null) { + return value.where((i) => i.name.contains(filterString)).toList(); + } + return value.toList(); + } +} + +@NgDirective( + selector: '[recipe-book]', + publishAs: 'ctrl') +class RecipeBookController { + + Http _http; + + List categories = ["Appetizers", "Salads", "Soups", "Main Dishes", + "Side Dishes", "Desserts"]; + List recipes = []; + + RecipeBookController(Http this._http) { + _loadData(); + } + + Recipe selectedRecipe; + + void selectRecipe(Recipe recipe) { + selectedRecipe = recipe; + } + + void _loadData() { + _http.get('/angular.dart.tutorial/Chapter_04/recipes.json') + .then((HttpResponse response) { + for (Map recipe in response.data) { + recipes.add(new Recipe.fromJson(recipe)); + } + }); + } +} + +main() { + var module = new AngularModule() + ..type(RecipeBookController) + ..type(RatingComponent) + ..type(SearchFilter); + + bootstrapAngular([module]); +} \ No newline at end of file diff --git a/Chapter_04/pubspec.yaml b/Chapter_04/pubspec.yaml new file mode 100644 index 0000000..c5b05c1 --- /dev/null +++ b/Chapter_04/pubspec.yaml @@ -0,0 +1,10 @@ +name: angular_dart_demo +version: 0.0.1 +dependencies: + angular: + git: https://github.com/angular/angular.dart.git + # git: https://github.com/mhevery/angular.dart.git + + browser: any + js: any + unittest: any diff --git a/Chapter_04/rating_component.css b/Chapter_04/rating_component.css new file mode 100644 index 0000000..114c9ae --- /dev/null +++ b/Chapter_04/rating_component.css @@ -0,0 +1,10 @@ +.star-off { + color: #6E6E6E; +} +.star-on { + color: #FACC2E; +} +.stars { + letter-spacing: -2px; + cursor: pointer; +} diff --git a/Chapter_04/rating_component.dart b/Chapter_04/rating_component.dart new file mode 100644 index 0000000..b84df07 --- /dev/null +++ b/Chapter_04/rating_component.dart @@ -0,0 +1,78 @@ +import 'package:angular/angular.dart'; + +/* Use the NgComponent annotation to indicate that this class is an + * Angular Component. + * + * The selector field defines the CSS selector that will trigger the + * component. Typically, the CSS selector is an element name. + * + * The templateUrl field tells the component which HTML template to use + * for its view. + * + * The cssUrl field tells the component which CSS file to use. + * + * The publishAs field specifies that the component instance should be + * assigned to the current scope under the name specified. + * + * The map field publishes the list of attributes that can be set on + * the component. Users of this component will specify these attributes + * in the html tag that is used to create the component. For example: + * + * + * + * TODO: adopt new map naming conventions as soon as they're ready. + * OLD: + * 'max' : '@.max', + * 'rating' : '=.rating' + * NEW: + * 'max-rating' : '@maxRating', + * 'rating' : '=rating' + * + * The compnoent's public fields are available for data binding from the + * component's view. Similarly, the component's public methods can be + * invoked from the component's view. + */ +@NgComponent( + selector: 'rating', + templateUrl: 'rating_component.html', + cssUrl: 'rating_component.css', + publishAs: 'ctrl', + map: const { + 'max' : '@.max', + 'rating' : '=.rating' + } +) +class RatingComponent { + String _starOnChar = "\u2605"; + String _starOffChar = "\u2606"; + String _starOnClass = "star-on"; + String _starOffClass = "star-off"; + + List stars = []; + + int rating; + + set max(String value) { + stars = []; + var count = value == null ? 5 : int.parse(value); + for(var i=1; i <= count; i++) { + stars.add(i); + } + } + + String starClass(int star) { + return star > rating ? _starOffClass : _starOnClass; + } + + String starChar(int star) { + return star > rating ? _starOffChar : _starOnChar; + } + + void handleClick(int star) { + if (star == 1 && rating == 1) { + rating = 0; + } else { + rating = star; + } + } +} diff --git a/Chapter_04/rating_component.html b/Chapter_04/rating_component.html new file mode 100644 index 0000000..4d4c94e --- /dev/null +++ b/Chapter_04/rating_component.html @@ -0,0 +1,7 @@ + + {{ctrl.starChar(star)}} + diff --git a/Chapter_04/recipe.dart b/Chapter_04/recipe.dart new file mode 100644 index 0000000..ca63544 --- /dev/null +++ b/Chapter_04/recipe.dart @@ -0,0 +1,30 @@ +library recipe; + +import 'dart:convert' show JSON; + +class Recipe { + String name; + String category; + List ingredients; + String directions; + int rating; + + Recipe(this.name, this.category, this.ingredients, this.directions, + this.rating); + + String toJson() { + Map data = { + "name" : name, + "category" : category, + "ingredients" : ingredients, + "directions" : directions, + "rating" : rating + }; + return JSON.encode(data); + } + + factory Recipe.fromJson(Map json) { + return new Recipe(json['name'], json['category'], json['ingredients'], + json['directions'], json['rating']); + } +} diff --git a/Chapter_04/recipes.json b/Chapter_04/recipes.json new file mode 100644 index 0000000..89c3a62 --- /dev/null +++ b/Chapter_04/recipes.json @@ -0,0 +1,51 @@ +[ + { + "name":"My Appetizer", + "category":"Appetizers", + "ingredients":["Ingredient 1","Ingredient 2"], + "directions":"Some Directions", + "rating": 1 + }, + { + "name":"My Salad", + "category":"Salads", + "ingredients":["Ingredient 1","Ingredient 2"], + "directions":"Some Directions", + "rating": 3 + }, + { + "name":"My Soup", + "category":"Soups", + "ingredients":["Ingredient 1","Ingredient 2"], + "directions":"Some Directions", + "rating": 4 + }, + { + "name":"My Main Dish", + "category":"Main Dishes", + "ingredients":["Ingredient 1","Ingredient 2"], + "directions":"Some Directions", + "rating": 2 + }, + { + "name":"My Side Dish", + "category":"Side Dishes", + "ingredients":["Ingredient 1","Ingredient 2"], + "directions":"Some Directions", + "rating": 3 + }, + { + "name":"My Awesome Dessert", + "category":"Desserts", + "ingredients":["Ingredient 1","Ingredient 2"], + "directions":"Some Directions", + "rating": 5 + }, + { + "name":"My So-So Dessert", + "category":"Desserts", + "ingredients":["Ingredient 1","Ingredient 2"], + "directions":"Some Directions", + "rating": 3 + } +] diff --git a/Chapter_04/style.css b/Chapter_04/style.css new file mode 100644 index 0000000..faa8964 --- /dev/null +++ b/Chapter_04/style.css @@ -0,0 +1,11 @@ +.pointer { + cursor: pointer; +} + +.extra-space { + padding-left: 10px; +} + +[ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { + display: none !important; +} \ No newline at end of file From b2183fb124a69929f4220e4bc77ece2c770eada2 Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Fri, 18 Oct 2013 17:08:07 -0700 Subject: [PATCH 10/21] add custom filter and built-in filter to chapter 4. fix pubspec.yamls to point to release, not git head --- Chapter_01/pubspec.yaml | 4 +- Chapter_02/pubspec.yaml | 4 +- Chapter_03/pubspec.yaml | 4 +- Chapter_04/categories.json | 8 ++++ Chapter_04/index.html | 70 ++++++++++++++++++++------------ Chapter_04/main.dart | 55 ++++++++++++++++++++----- Chapter_04/pubspec.yaml | 3 +- Chapter_04/rating_component.dart | 8 ++-- Chapter_04/recipe.dart | 4 +- Chapter_04/style.css | 4 ++ 10 files changed, 114 insertions(+), 50 deletions(-) create mode 100644 Chapter_04/categories.json diff --git a/Chapter_01/pubspec.yaml b/Chapter_01/pubspec.yaml index c5b05c1..7b19e75 100644 --- a/Chapter_01/pubspec.yaml +++ b/Chapter_01/pubspec.yaml @@ -1,8 +1,8 @@ name: angular_dart_demo version: 0.0.1 dependencies: - angular: - git: https://github.com/angular/angular.dart.git + angular: 0.0.2 + # git: https://github.com/angular/angular.dart.git # git: https://github.com/mhevery/angular.dart.git browser: any diff --git a/Chapter_02/pubspec.yaml b/Chapter_02/pubspec.yaml index c5b05c1..7b19e75 100644 --- a/Chapter_02/pubspec.yaml +++ b/Chapter_02/pubspec.yaml @@ -1,8 +1,8 @@ name: angular_dart_demo version: 0.0.1 dependencies: - angular: - git: https://github.com/angular/angular.dart.git + angular: 0.0.2 + # git: https://github.com/angular/angular.dart.git # git: https://github.com/mhevery/angular.dart.git browser: any diff --git a/Chapter_03/pubspec.yaml b/Chapter_03/pubspec.yaml index c5b05c1..7b19e75 100644 --- a/Chapter_03/pubspec.yaml +++ b/Chapter_03/pubspec.yaml @@ -1,8 +1,8 @@ name: angular_dart_demo version: 0.0.1 dependencies: - angular: - git: https://github.com/angular/angular.dart.git + angular: 0.0.2 + # git: https://github.com/angular/angular.dart.git # git: https://github.com/mhevery/angular.dart.git browser: any diff --git a/Chapter_04/categories.json b/Chapter_04/categories.json new file mode 100644 index 0000000..9d84deb --- /dev/null +++ b/Chapter_04/categories.json @@ -0,0 +1,8 @@ +[ + "Appetizers", + "Salads", + "Soups", + "Main Dishes", + "Side Dishes", + "Desserts" +] diff --git a/Chapter_04/index.html b/Chapter_04/index.html index b71effb..1cfb98f 100644 --- a/Chapter_04/index.html +++ b/Chapter_04/index.html @@ -9,36 +9,54 @@

      Recipe List

      - - - -
        -
      • - - {{recipe.name}} -
      • -
      - -

      Recipe Details

      -
      -
      Name: {{ctrl.selectedRecipe.name}}
      -
      Category: {{ctrl.selectedRecipe.category}}
      -
      Rating: - +
      +
      + +
      -
        -
      • - {{ingredient}} -
      • -
      + + + {{category}} + +
      + +
      + +
      +
        +
      • + + {{recipe.name}} +
      • +
      +
      + +
      +

      Recipe Details

      +
      +
      Name: {{ctrl.selectedRecipe.name}}
      +
      Category: {{ctrl.selectedRecipe.category}}
      +
      Rating: + +
      +
      +
        +
      • + {{ingredient}} +
      • +
      +
      +
      Directions: {{ctrl.selectedRecipe.directions}}
      -
      Directions: {{ctrl.selectedRecipe.directions}}
      -
      + +
      diff --git a/Chapter_04/main.dart b/Chapter_04/main.dart index 9ada884..7669f79 100644 --- a/Chapter_04/main.dart +++ b/Chapter_04/main.dart @@ -3,13 +3,17 @@ import 'package:di/di.dart'; import 'rating_component.dart'; import 'recipe.dart'; -@NgFilter(name: 'searchfilter') -class SearchFilter { - call(value, filterString) { - if (value is List && filterString != null) { - return value.where((i) => i.name.contains(filterString)).toList(); +@NgFilter(name: 'categoryfilter') +class CategoryFilter { + call(recipeList, filterMap) { + if (recipeList is List && filterMap != null && filterMap is Map) { + // If there is nothing checked, treat it as everything is checked. + bool nothingChecked = filterMap.values.every((isChecked) => !isChecked); + if (nothingChecked) { + return recipeList.toList(); + } + return recipeList.where((i) => filterMap[i.category] == true).toList(); } - return value.toList(); } } @@ -18,12 +22,22 @@ class SearchFilter { publishAs: 'ctrl') class RecipeBookController { + static const String LOADING_MESSAGE = "Loading recipe book..."; + static const String ERROR_MESSAGE = """Sorry! The cook stepped out of the +kitchen and took the recipe book with him!"""; + Http _http; - List categories = ["Appetizers", "Salads", "Soups", "Main Dishes", - "Side Dishes", "Desserts"]; + String loadingMessage = "Loading recipe book..."; + + // Data objects that are loaded from the server side via json + List categories = []; List recipes = []; + // Filter box + Map categoryFilterMap = {}; + String nameFilter = ""; + RecipeBookController(Http this._http) { _loadData(); } @@ -34,13 +48,32 @@ class RecipeBookController { selectedRecipe = recipe; } + void clearFilters() { + categoryFilterMap.keys.forEach((f) => categoryFilterMap[f] = false); + nameFilter = ""; + } + void _loadData() { _http.get('/angular.dart.tutorial/Chapter_04/recipes.json') .then((HttpResponse response) { for (Map recipe in response.data) { - recipes.add(new Recipe.fromJson(recipe)); + recipes.add(new Recipe.fromJsonMap(recipe)); } + }, + onError: (Object obj) { + loadingMessage = ERROR_MESSAGE; }); + + _http.get('/angular.dart.tutorial/Chapter_04/categories.json') + .then((HttpResponse response) { + for (String category in response.data) { + categories.add(category); + categoryFilterMap[category] = false; + } + }, + onError: (Object obj) { + loadingMessage = ERROR_MESSAGE; + }); } } @@ -48,7 +81,7 @@ main() { var module = new AngularModule() ..type(RecipeBookController) ..type(RatingComponent) - ..type(SearchFilter); + ..type(CategoryFilter); - bootstrapAngular([module]); + ngBootstrap(module: module); } \ No newline at end of file diff --git a/Chapter_04/pubspec.yaml b/Chapter_04/pubspec.yaml index c5b05c1..8b6bc5d 100644 --- a/Chapter_04/pubspec.yaml +++ b/Chapter_04/pubspec.yaml @@ -1,7 +1,8 @@ name: angular_dart_demo version: 0.0.1 dependencies: - angular: + angular: + # 0.0.2 git: https://github.com/angular/angular.dart.git # git: https://github.com/mhevery/angular.dart.git diff --git a/Chapter_04/rating_component.dart b/Chapter_04/rating_component.dart index b84df07..2ed1355 100644 --- a/Chapter_04/rating_component.dart +++ b/Chapter_04/rating_component.dart @@ -26,7 +26,7 @@ import 'package:angular/angular.dart'; * 'rating' : '=.rating' * NEW: * 'max-rating' : '@maxRating', - * 'rating' : '=rating' + * 'rating' : '<=>rating' * * The compnoent's public fields are available for data binding from the * component's view. Similarly, the component's public methods can be @@ -38,8 +38,8 @@ import 'package:angular/angular.dart'; cssUrl: 'rating_component.css', publishAs: 'ctrl', map: const { - 'max' : '@.max', - 'rating' : '=.rating' + 'max-rating' : '@maxRating', + 'rating' : '<=>rating' } ) class RatingComponent { @@ -52,7 +52,7 @@ class RatingComponent { int rating; - set max(String value) { + set maxRating(String value) { stars = []; var count = value == null ? 5 : int.parse(value); for(var i=1; i <= count; i++) { diff --git a/Chapter_04/recipe.dart b/Chapter_04/recipe.dart index ca63544..083f448 100644 --- a/Chapter_04/recipe.dart +++ b/Chapter_04/recipe.dart @@ -12,7 +12,7 @@ class Recipe { Recipe(this.name, this.category, this.ingredients, this.directions, this.rating); - String toJson() { + String toJsonString() { Map data = { "name" : name, "category" : category, @@ -23,7 +23,7 @@ class Recipe { return JSON.encode(data); } - factory Recipe.fromJson(Map json) { + factory Recipe.fromJsonMap(Map json) { return new Recipe(json['name'], json['category'], json['ingredients'], json['directions'], json['rating']); } diff --git a/Chapter_04/style.css b/Chapter_04/style.css index faa8964..d575a8a 100644 --- a/Chapter_04/style.css +++ b/Chapter_04/style.css @@ -8,4 +8,8 @@ [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { display: none !important; +} + +ul { + list-style-type: none; } \ No newline at end of file From 26a52372aff9a71ece945f4414bd09498e02f5fb Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Mon, 21 Oct 2013 14:53:38 -0700 Subject: [PATCH 11/21] minor code clean up --- Chapter_04/index.html | 5 ++--- Chapter_04/main.dart | 10 +++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Chapter_04/index.html b/Chapter_04/index.html index 1cfb98f..ef26e8b 100644 --- a/Chapter_04/index.html +++ b/Chapter_04/index.html @@ -29,7 +29,7 @@

      Recipe List

      • + ng-repeat="recipe in ctrl.recipes | filter:{name:ctrl.nameFilter} | categoryfilter:ctrl.categoryFilterMap"> {{recipe.name}} @@ -55,9 +55,8 @@

        Recipe Details

        Directions: {{ctrl.selectedRecipe.directions}}
      -
    - + diff --git a/Chapter_04/main.dart b/Chapter_04/main.dart index 7669f79..9e7a0a8 100644 --- a/Chapter_04/main.dart +++ b/Chapter_04/main.dart @@ -1,4 +1,5 @@ import 'package:angular/angular.dart'; +import 'package:perf_api/perf_api.dart'; import 'package:di/di.dart'; import 'rating_component.dart'; import 'recipe.dart'; @@ -7,7 +8,7 @@ import 'recipe.dart'; class CategoryFilter { call(recipeList, filterMap) { if (recipeList is List && filterMap != null && filterMap is Map) { - // If there is nothing checked, treat it as everything is checked. + // If there is nothing checked, treat it as "everything is checked" bool nothingChecked = filterMap.values.every((isChecked) => !isChecked); if (nothingChecked) { return recipeList.toList(); @@ -22,6 +23,7 @@ class CategoryFilter { publishAs: 'ctrl') class RecipeBookController { + // TODO: do something with these messages...put up status while loading... static const String LOADING_MESSAGE = "Loading recipe book..."; static const String ERROR_MESSAGE = """Sorry! The cook stepped out of the kitchen and took the recipe book with him!"""; @@ -77,11 +79,13 @@ kitchen and took the recipe book with him!"""; } } +// TODO - Remove the Profiler type. It's only needed to get rid of Misko's spam main() { var module = new AngularModule() ..type(RecipeBookController) ..type(RatingComponent) - ..type(CategoryFilter); + ..type(CategoryFilter) + ..type(Profiler, implementedBy: Profiler); ngBootstrap(module: module); -} \ No newline at end of file +} From 714a4cf71131530bd1c894c9e5dc48e2a7850de4 Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Tue, 22 Oct 2013 11:47:56 -0700 Subject: [PATCH 12/21] adding conditional on load display logic. --- Chapter_04/index.html | 90 +++++++++++++++++++++++-------------------- Chapter_04/main.dart | 18 +++++++-- 2 files changed, 62 insertions(+), 46 deletions(-) diff --git a/Chapter_04/index.html b/Chapter_04/index.html index ef26e8b..23a4505 100644 --- a/Chapter_04/index.html +++ b/Chapter_04/index.html @@ -7,54 +7,60 @@
    -

    Recipe List

    - -
    -
    - - -
    -
    - - - {{category}} - -
    - +
    + {{ctrl.message}}
    - -
    -
      -
    • - - {{recipe.name}} -
    • -
    -
    - -
    -

    Recipe Details

    -
    -
    Name: {{ctrl.selectedRecipe.name}}
    -
    Category: {{ctrl.selectedRecipe.category}}
    -
    Rating: - +
    +

    Recipe List

    + +
    +
    + +
    -
      -
    • - {{ingredient}} -
    • -
    + + + {{category}} + +
    + +
    + +
    +
      +
    • + + {{recipe.name}} +
    • +
    +
    + +
    +

    Recipe Details

    +
    +
    Name: {{ctrl.selectedRecipe.name}}
    +
    Category: {{ctrl.selectedRecipe.category}}
    +
    Rating: + +
    +
    +
      +
    • + {{ingredient}} +
    • +
    +
    +
    Directions: {{ctrl.selectedRecipe.directions}}
    -
    Directions: {{ctrl.selectedRecipe.directions}}
    +
    diff --git a/Chapter_04/main.dart b/Chapter_04/main.dart index 9e7a0a8..08b7cf7 100644 --- a/Chapter_04/main.dart +++ b/Chapter_04/main.dart @@ -4,6 +4,7 @@ import 'package:di/di.dart'; import 'rating_component.dart'; import 'recipe.dart'; + @NgFilter(name: 'categoryfilter') class CategoryFilter { call(recipeList, filterMap) { @@ -23,14 +24,16 @@ class CategoryFilter { publishAs: 'ctrl') class RecipeBookController { - // TODO: do something with these messages...put up status while loading... static const String LOADING_MESSAGE = "Loading recipe book..."; static const String ERROR_MESSAGE = """Sorry! The cook stepped out of the kitchen and took the recipe book with him!"""; Http _http; - String loadingMessage = "Loading recipe book..."; + // Determine the initial load state of the app + String message = LOADING_MESSAGE; + bool recipesLoaded = false; + bool categoriesLoaded = false; // Data objects that are loaded from the server side via json List categories = []; @@ -56,14 +59,19 @@ kitchen and took the recipe book with him!"""; } void _loadData() { + recipesLoaded = false; + categoriesLoaded = false; + _http.get('/angular.dart.tutorial/Chapter_04/recipes.json') .then((HttpResponse response) { for (Map recipe in response.data) { recipes.add(new Recipe.fromJsonMap(recipe)); } + recipesLoaded = true; }, onError: (Object obj) { - loadingMessage = ERROR_MESSAGE; + recipesLoaded = false; + message = ERROR_MESSAGE; }); _http.get('/angular.dart.tutorial/Chapter_04/categories.json') @@ -72,9 +80,11 @@ kitchen and took the recipe book with him!"""; categories.add(category); categoryFilterMap[category] = false; } + categoriesLoaded = true; }, onError: (Object obj) { - loadingMessage = ERROR_MESSAGE; + categoriesLoaded = false; + message = ERROR_MESSAGE; }); } } From f35e6ec510ae1ae0d0ee38c89167b673da4576c0 Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Tue, 22 Oct 2013 14:56:20 -0700 Subject: [PATCH 13/21] adding orderBy built in filter. Changing recipes so they're more interesting --- Chapter_04/index.html | 4 +- Chapter_04/recipes.json | 114 ++++++++++++++++++++++++++++++++-------- 2 files changed, 94 insertions(+), 24 deletions(-) diff --git a/Chapter_04/index.html b/Chapter_04/index.html index 23a4505..f913971 100644 --- a/Chapter_04/index.html +++ b/Chapter_04/index.html @@ -12,7 +12,7 @@

    Recipe List

    - +
    @@ -33,7 +33,7 @@

    Recipe List

    • + ng-repeat="recipe in ctrl.recipes | orderBy:'name' | filter:{name:ctrl.nameFilter} | categoryfilter:ctrl.categoryFilterMap"> {{recipe.name}} diff --git a/Chapter_04/recipes.json b/Chapter_04/recipes.json index 89c3a62..a55e63e 100644 --- a/Chapter_04/recipes.json +++ b/Chapter_04/recipes.json @@ -1,51 +1,121 @@ [ { - "name":"My Appetizer", + "name":"Bleu Cheese Stuffed Mushrooms", "category":"Appetizers", - "ingredients":["Ingredient 1","Ingredient 2"], - "directions":"Some Directions", + "ingredients":[ + "12 mushrooms", + "8 oz bleu cheese", + "1/2 red onion, diced", + "1/4 cup bread crumbs", + "1/4 cup parmesan cheese" + ], + "directions":"Preheat oven to 250 degrees. Clean the mushrooms. Break the stems off, chop and set aside. Combine bleu cheese, red onions, bread crumbs and chopped mushroom stems. Fill each mushroom with the bleu cheese mixture and place on a baking sheet. Bake for 20 minutes, or until the tops are golden. Sprinkle with parmesan cheese if desired.", "rating": 1 }, { - "name":"My Salad", + "name":"Cannelini Bean and Mushroom Salad", "category":"Salads", - "ingredients":["Ingredient 1","Ingredient 2"], - "directions":"Some Directions", + "ingredients":[ + "2 cups cannelini", + "a large handful of mushrooms, sliced", + "3 tbsp italian parsley", + "2 tbsp fresh thyme", + "3 tbsp fresh chives", + "a handful of cherry tomatoes, halved", + "slices of parmesan cheese", + "lemon juice", + "olive oil", + "1 garlic clove", + "salt" + ], + "directions":"Cook and drain the beans. Coat mushrooms with olive oil and grill or pan fry them. Combine the beans, mushrooms, herbs and tomatoes. Combine lemon juice, olive oil, garlic and salt and make an emulsion. Pour the dressing over the bean mixture and stir to combine. Use a carrot peeler to peel some parmesan cheese over the top.", "rating": 3 }, { - "name":"My Soup", + "name":"Pumpkin Black Bean Soup", "category":"Soups", - "ingredients":["Ingredient 1","Ingredient 2"], - "directions":"Some Directions", - "rating": 4 + "ingredients":[ + "2 tablespoon extra-virgin olive oil", + "1 medium onion, finely chopped", + "3 cups canned or packaged vegetable stock, found on soup aisle", + "1 can (14 1/2 ounces) diced tomatoes in juice", + "1 can (15 ounces) black beans, drained", + "2 cans (15 ounces) pumpkin puree", + "1 cup heavy cream", + "1 tablespoon curry powder", + "1 1/2 teaspoons ground cumin", + "1/2 teaspoon cayenne pepper", + "Coarse salt", + "20 blades fresh chives, chopped or snipped, for garnish" + ], + "directions":"Add oil to a soup pot on medium heat. When oil is hot, add onion. Saute onions 5 minutes. Add broth, tomatoes, black beans and pumpkin puree. Stir to combine ingredients and bring soup to a boil. Reduce heat to medium low and stir in cream, curry, cumin, cayenne and salt, to taste. Simmer 5 minutes, adjust seasonings and serve garnished with chopped chives.", + "rating": 3 }, { - "name":"My Main Dish", + "name":"Smoked Salmon Pasta", "category":"Main Dishes", - "ingredients":["Ingredient 1","Ingredient 2"], - "directions":"Some Directions", + "ingredients":[ + "8 ounces spaghetti (or other) pasta", + "1/4 cup pine nuts", + "2 Tbsp olive oil", + "1/3 cup chopped shallots (can substitute onions)", + "2 cloves garlic, minced", + "1/3 cup dry white wine", + "1/4 cup cream", + "2 Tbsp lemon zest", + "1 Tbsp lemon juice", + "2 Tbsp chopped fresh parsley or dill", + "4 ounces smoked salmon, cut into bite sized pieces", + "pinch salt", + "Fresh ground black pepper" + ], + "directions":"Bring a pot of water to a boil over high heat to cook the pasta. Meanwhile, toast the pine nuts in a dry pan or toaster oven and set aside. Add olive oil to a sauce pan on medium heat. Add shallots and cook for 5 minutes until soft and just beginning to caramelize. Add garlic and cook until garlic is soft, but not brown. Add wine and reduce. Turn heat to low and add cream (heat needs to be low, or the cream will curdle). When the pasta is finished cooking, drain it and add to the sauce pan. Turn the heat off and stir to combine. Add lemon juice, parsley or dill, pine nuts, and salmon. Add salt and pepper to taste.", "rating": 2 }, { - "name":"My Side Dish", + "name":"Pancetta Brussels Sprouts", "category":"Side Dishes", - "ingredients":["Ingredient 1","Ingredient 2"], - "directions":"Some Directions", + "ingredients":[ + "1 lb brussels sprouts", + "1 tbsp olive oil", + "1 tbsp butter", + "1/4 cup pancetta, chopped", + "splash of balsamic vinegar" + ], + "directions":"Wash brussels sprouts, and chop in half. In a pan over medium heat, melt the oil and butter. Add sprouts and pancetta and turn heat to high. Cook until the sprouts are caramelized. Deglaze the pan with a splash of balsamic vinegar.", "rating": 3 }, { - "name":"My Awesome Dessert", + "name":"Almond Cookies With Chai Spices", "category":"Desserts", - "ingredients":["Ingredient 1","Ingredient 2"], - "directions":"Some Directions", + "ingredients":[ + "1/2 cup unsalted butter, room temperature", + "1 1/3 cups powdered sugar, divided", + "2 tsp vanilla extract", + "1 tsp almond extract", + "3/4 tsp ground allspice", + "3/4 tsp ground cardamom", + "1/2 tsp ground cinnamon", + "1/4 tsp salt", + "1 cup all purpose flour", + "3/4 cup finely chopped toasted almonds" + ], + "directions":"Preheat oven to 350 degrees. Using electric mixer, beat butter, 1/3 cup sugar, both extracts, spices, and salt in medium bowl. Beat in flour, then stir in almonds. Using hands, roll dough into tablespoon-size balls. Place on large baking sheet, spacing apart. Bake until pale golden, about 25 minutes. Cool on sheet 5 minutes. Place remaining sugar in large bowl. Working in batches, gently coat hot cookies in sugar. Cool cookies on rack. Roll again in sugar and serve. ", "rating": 5 }, { - "name":"My So-So Dessert", + "name":"Cardamom Poached Pears", "category":"Desserts", - "ingredients":["Ingredient 1","Ingredient 2"], - "directions":"Some Directions", + "ingredients":[ + "2 pears, peeled", + "1 1/4 cups water", + "1/2 cup sugar", + "3 2 inch strips of lemon zest", + "1 cracked whole cardamom", + "A couple grinds of fresh shaved nutmeg", + "vanilla" + ], + "directions":"Combine all ingredients except the pears in a sauce pan and simmer for 10 minutes. Add the pears to the pan and cook, turning the pears occasionally so that all sides cook evenly. Cook for about 10 minutes, or until pears are soft enough to be poked with a fork.", "rating": 3 } ] From deb9cfc07d75896da8036f03aec2031eba61ceab Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Wed, 23 Oct 2013 09:42:59 -0700 Subject: [PATCH 14/21] making more normal dart packages and libraries --- Chapter_03/main.dart | 5 ++++- Chapter_03/rating_component.dart | 2 +- Chapter_04/main.dart | 8 ++++++-- Chapter_04/rating_component.dart | 2 +- Chapter_04/recipe.dart | 4 +--- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/Chapter_03/main.dart b/Chapter_03/main.dart index 61c9de7..a38ba1e 100644 --- a/Chapter_03/main.dart +++ b/Chapter_03/main.dart @@ -1,6 +1,9 @@ +library recipe_book; + import 'package:angular/angular.dart'; import 'package:di/di.dart'; -import 'rating_component.dart'; + +part 'rating_component.dart'; @NgDirective( selector: '[recipe-book]', diff --git a/Chapter_03/rating_component.dart b/Chapter_03/rating_component.dart index b84df07..d93ba95 100644 --- a/Chapter_03/rating_component.dart +++ b/Chapter_03/rating_component.dart @@ -1,4 +1,4 @@ -import 'package:angular/angular.dart'; +part of recipe_book; /* Use the NgComponent annotation to indicate that this class is an * Angular Component. diff --git a/Chapter_04/main.dart b/Chapter_04/main.dart index 08b7cf7..db8ec6e 100644 --- a/Chapter_04/main.dart +++ b/Chapter_04/main.dart @@ -1,8 +1,12 @@ +library recipe_book; + import 'package:angular/angular.dart'; +import 'dart:convert'; import 'package:perf_api/perf_api.dart'; import 'package:di/di.dart'; -import 'rating_component.dart'; -import 'recipe.dart'; + +part 'rating_component.dart'; +part 'recipe.dart'; @NgFilter(name: 'categoryfilter') diff --git a/Chapter_04/rating_component.dart b/Chapter_04/rating_component.dart index 2ed1355..3639717 100644 --- a/Chapter_04/rating_component.dart +++ b/Chapter_04/rating_component.dart @@ -1,4 +1,4 @@ -import 'package:angular/angular.dart'; +part of recipe_book; /* Use the NgComponent annotation to indicate that this class is an * Angular Component. diff --git a/Chapter_04/recipe.dart b/Chapter_04/recipe.dart index 083f448..cb3ab0b 100644 --- a/Chapter_04/recipe.dart +++ b/Chapter_04/recipe.dart @@ -1,6 +1,4 @@ -library recipe; - -import 'dart:convert' show JSON; +part of recipe_book; class Recipe { String name; From a929eb77f9324db19b02c8244a6bb33edccc1ebf Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Wed, 23 Oct 2013 16:50:46 -0700 Subject: [PATCH 15/21] initial commit. this cl contains routing, creating a normal package/library structure, separating out components and filters to their own files, and stubs out a (currently failing) query service. But the app still works. --- Chapter_05/add.html | 3 + Chapter_05/categories.json | 8 ++ Chapter_05/category_filter.dart | 16 +++ Chapter_05/edit.html | 3 + Chapter_05/index.html | 57 ++++++++++ Chapter_05/main.dart | 121 +++++++++++++++++++++ Chapter_05/query_service.dart | 56 ++++++++++ Chapter_05/rating_component.css | 10 ++ Chapter_05/rating_component.dart | 70 +++++++++++++ Chapter_05/rating_component.html | 7 ++ Chapter_05/recipe.dart | 30 ++++++ Chapter_05/recipe_book_router.dart | 24 +++++ Chapter_05/recipe_details_component.css | 0 Chapter_05/recipe_details_component.dart | 28 +++++ Chapter_05/recipe_details_component.html | 19 ++++ Chapter_05/recipe_search_component.css | 0 Chapter_05/recipe_search_component.dart | 25 +++++ Chapter_05/recipe_search_component.html | 16 +++ Chapter_05/recipes.json | 128 +++++++++++++++++++++++ Chapter_05/style.css | 28 +++++ Chapter_05/view.html | 6 ++ 21 files changed, 655 insertions(+) create mode 100644 Chapter_05/add.html create mode 100644 Chapter_05/categories.json create mode 100644 Chapter_05/category_filter.dart create mode 100644 Chapter_05/edit.html create mode 100644 Chapter_05/index.html create mode 100644 Chapter_05/main.dart create mode 100644 Chapter_05/query_service.dart create mode 100644 Chapter_05/rating_component.css create mode 100644 Chapter_05/rating_component.dart create mode 100644 Chapter_05/rating_component.html create mode 100644 Chapter_05/recipe.dart create mode 100644 Chapter_05/recipe_book_router.dart create mode 100644 Chapter_05/recipe_details_component.css create mode 100644 Chapter_05/recipe_details_component.dart create mode 100644 Chapter_05/recipe_details_component.html create mode 100644 Chapter_05/recipe_search_component.css create mode 100644 Chapter_05/recipe_search_component.dart create mode 100644 Chapter_05/recipe_search_component.html create mode 100644 Chapter_05/recipes.json create mode 100644 Chapter_05/style.css create mode 100644 Chapter_05/view.html diff --git a/Chapter_05/add.html b/Chapter_05/add.html new file mode 100644 index 0000000..62d43e4 --- /dev/null +++ b/Chapter_05/add.html @@ -0,0 +1,3 @@ +
      +Add recipe +
      diff --git a/Chapter_05/categories.json b/Chapter_05/categories.json new file mode 100644 index 0000000..9d84deb --- /dev/null +++ b/Chapter_05/categories.json @@ -0,0 +1,8 @@ +[ + "Appetizers", + "Salads", + "Soups", + "Main Dishes", + "Side Dishes", + "Desserts" +] diff --git a/Chapter_05/category_filter.dart b/Chapter_05/category_filter.dart new file mode 100644 index 0000000..d5377dd --- /dev/null +++ b/Chapter_05/category_filter.dart @@ -0,0 +1,16 @@ +part of recipe_book; + +@NgFilter(name: 'categoryfilter') +class CategoryFilter { + call(recipeList, filterMap) { + if (recipeList is List && filterMap != null && filterMap is Map) { + // If there is nothing checked, treat it as "everything is checked" + bool nothingChecked = filterMap.values.every((isChecked) => !isChecked); + if (nothingChecked) { + return recipeList.toList(); + } + return recipeList.where((i) => filterMap[i.category] == true).toList(); + } + } +} + diff --git a/Chapter_05/edit.html b/Chapter_05/edit.html new file mode 100644 index 0000000..a45d43a --- /dev/null +++ b/Chapter_05/edit.html @@ -0,0 +1,3 @@ +
      +Edit recipe +
      diff --git a/Chapter_05/index.html b/Chapter_05/index.html new file mode 100644 index 0000000..02f13b6 --- /dev/null +++ b/Chapter_05/index.html @@ -0,0 +1,57 @@ + + + + Chapter Five - A Simple Recipe Book + + + +
      + + + +
      +
      + {{ctrl.message}} +
      + + +
      +
      + + + + + + + + + diff --git a/Chapter_05/main.dart b/Chapter_05/main.dart new file mode 100644 index 0000000..3df7251 --- /dev/null +++ b/Chapter_05/main.dart @@ -0,0 +1,121 @@ +library recipe_book; + +import 'package:angular/angular.dart'; +import 'package:angular/routing/module.dart'; +import 'dart:convert'; +import 'package:perf_api/perf_api.dart'; +import 'package:logging/logging.dart'; +import 'package:di/di.dart'; + +part 'category_filter.dart'; +part 'query_service.dart'; +part 'rating_component.dart'; +part 'recipe.dart'; +part 'recipe_book_router.dart'; +part 'recipe_details_component.dart'; +part 'recipe_search_component.dart'; + +@NgDirective( + selector: '[recipe-book]', + publishAs: 'ctrl') +class RecipeBookController { + + static const String LOADING_MESSAGE = "Loading recipe book..."; + static const String ERROR_MESSAGE = """Sorry! The cook stepped out of the +kitchen and took the recipe book with him!"""; + + Http _http; + QueryService _queryService; + QueryService get queryService => _queryService; + + // Determine the initial load state of the app + String message = LOADING_MESSAGE; + bool recipesLoaded = false; + bool categoriesLoaded = false; + + // Data objects that are loaded from the server side via json + List categories = []; + List recipes = []; + + // get rid of this and replace with a recipe service + Map recipeMap = {}; + + List get foofoo => recipeMap.values.toList(); + + // Filter box + Map categoryFilterMap = {}; + String nameFilter = ""; + + RecipeBookController(Http this._http, QueryService this._queryService) { + _loadData(); + } + + Recipe selectedRecipe; + + void selectRecipe(Recipe recipe) { + selectedRecipe = recipe; + } + + void _loadData() { + recipesLoaded = false; + categoriesLoaded = false; + +// _queryService.loadData(); +// recipesLoaded = _queryService.recipesLoaded; +// categoriesLoaded = _queryService.categoriesLoaded; +// +// if (!recipesLoaded || !categoriesLoaded) { +// message = ERROR_MESSAGE; +// } + + _http.get('/angular.dart.tutorial/Chapter_05/recipes.json') + .then((HttpResponse response) { + for (Map recipe in response.data) { + Recipe r = new Recipe.fromJsonMap(recipe); + recipes.add(r); + recipeMap[r.id] = r; + } + recipesLoaded = true; + for (Recipe r in recipeMap.values) { + print(r.name); + } + }, + onError: (Object obj) { + recipesLoaded = false; + message = ERROR_MESSAGE; + }); + + _http.get('/angular.dart.tutorial/Chapter_05/categories.json') + .then((HttpResponse response) { + for (String category in response.data) { + categories.add(category); + categoryFilterMap[category] = false; + } + categoriesLoaded = true; + }, + onError: (Object obj) { + categoriesLoaded = false; + message = ERROR_MESSAGE; + }); + } +} + +// TODO - Remove the Profiler type. It's only needed to get rid of Misko's spam +main() { +// Logger.root.level = Level.FINEST; +// Logger.root.onRecord.listen((LogRecord r) { print(r.message); }); + + var module = new AngularModule() + ..type(RecipeBookController) + ..type(RatingComponent) + ..type(RecipeSearchComponent) + ..type(RecipeDetailsComponent) + ..type(CategoryFilter) + ..type(QueryService) + ..type(RouteInitializer, implementedBy: RecipeBookRouteInitializer) + ..factory(NgRoutingUsePushState, + (_) => new NgRoutingUsePushState.value(false)) + ..type(Profiler, implementedBy: Profiler); + + ngBootstrap(module: module); +} diff --git a/Chapter_05/query_service.dart b/Chapter_05/query_service.dart new file mode 100644 index 0000000..9e4b8a1 --- /dev/null +++ b/Chapter_05/query_service.dart @@ -0,0 +1,56 @@ +part of recipe_book; + +class QueryService { + String _recipesUrl = '/angular.dart.tutorial/Chapter_05/recipes.json'; + String _categoriesUrl = '/angular.dart.tutorial/Chapter_05/categories.json'; + + Map _recipes = {}; + List _categories = []; + + bool _recipesLoaded = false; + bool _categoriesLoaded = false; + Http _http; + + QueryService(Http this._http); + + void loadData() { + _recipesLoaded = false; + _categoriesLoaded = false; + + _http.get(_recipesUrl) + .then((HttpResponse response) { + for (Map recipe in response.data) { + Recipe r = new Recipe.fromJsonMap(recipe); + _recipes[r.id] = r; + } + _recipesLoaded = true; + }, + onError: (Object obj) { + _recipesLoaded = false; + }); + + _http.get(_categoriesUrl) + .then((HttpResponse response) { + for (String category in response.data) { + _categories.add(category); + } + _categoriesLoaded = true; + }, + onError: (Object obj) { + _categoriesLoaded = false; + }); + } + + Recipe getRecipeById(String id) { + return _recipes[id]; + } + + List getAllRecipes() { + return _recipes.values.toList(); + } + + bool get recipesLoaded => _recipesLoaded; + + bool get categoriesLoaded => _categoriesLoaded; + +} \ No newline at end of file diff --git a/Chapter_05/rating_component.css b/Chapter_05/rating_component.css new file mode 100644 index 0000000..114c9ae --- /dev/null +++ b/Chapter_05/rating_component.css @@ -0,0 +1,10 @@ +.star-off { + color: #6E6E6E; +} +.star-on { + color: #FACC2E; +} +.stars { + letter-spacing: -2px; + cursor: pointer; +} diff --git a/Chapter_05/rating_component.dart b/Chapter_05/rating_component.dart new file mode 100644 index 0000000..c3a0ae6 --- /dev/null +++ b/Chapter_05/rating_component.dart @@ -0,0 +1,70 @@ +part of recipe_book; + +/* Use the NgComponent annotation to indicate that this class is an + * Angular Component. + * + * The selector field defines the CSS selector that will trigger the + * component. Typically, the CSS selector is an element name. + * + * The templateUrl field tells the component which HTML template to use + * for its view. + * + * The cssUrl field tells the component which CSS file to use. + * + * The publishAs field specifies that the component instance should be + * assigned to the current scope under the name specified. + * + * The map field publishes the list of attributes that can be set on + * the component. Users of this component will specify these attributes + * in the html tag that is used to create the component. For example: + * + * + * + * The compnoent's public fields are available for data binding from the + * component's view. Similarly, the component's public methods can be + * invoked from the component's view. + */ +@NgComponent( + selector: 'rating', + templateUrl: 'rating_component.html', + cssUrl: 'rating_component.css', + publishAs: 'ctrl', + map: const { + 'max-rating' : '@maxRating', + 'rating' : '<=>rating' + } +) +class RatingComponent { + String _starOnChar = "\u2605"; + String _starOffChar = "\u2606"; + String _starOnClass = "star-on"; + String _starOffClass = "star-off"; + + List stars = []; + + int rating; + + set maxRating(String value) { + stars = []; + var count = value == null ? 5 : int.parse(value); + for(var i=1; i <= count; i++) { + stars.add(i); + } + } + + String starClass(int star) { + return star > rating ? _starOffClass : _starOnClass; + } + + String starChar(int star) { + return star > rating ? _starOffChar : _starOnChar; + } + + void handleClick(int star) { + if (star == 1 && rating == 1) { + rating = 0; + } else { + rating = star; + } + } +} diff --git a/Chapter_05/rating_component.html b/Chapter_05/rating_component.html new file mode 100644 index 0000000..4d4c94e --- /dev/null +++ b/Chapter_05/rating_component.html @@ -0,0 +1,7 @@ + + {{ctrl.starChar(star)}} + diff --git a/Chapter_05/recipe.dart b/Chapter_05/recipe.dart new file mode 100644 index 0000000..2144b38 --- /dev/null +++ b/Chapter_05/recipe.dart @@ -0,0 +1,30 @@ +part of recipe_book; + +class Recipe { + String id; + String name; + String category; + List ingredients; + String directions; + int rating; + + Recipe(this.id, this.name, this.category, this.ingredients, this.directions, + this.rating); + + String toJsonString() { + Map data = { + "id" : id, + "name" : name, + "category" : category, + "ingredients" : ingredients, + "directions" : directions, + "rating" : rating + }; + return JSON.encode(data); + } + + factory Recipe.fromJsonMap(Map json) { + return new Recipe(json['id'], json['name'], json['category'], + json['ingredients'], json['directions'], json['rating']); + } +} diff --git a/Chapter_05/recipe_book_router.dart b/Chapter_05/recipe_book_router.dart new file mode 100644 index 0000000..e425066 --- /dev/null +++ b/Chapter_05/recipe_book_router.dart @@ -0,0 +1,24 @@ +part of recipe_book; + +class RecipeBookRouteInitializer implements RouteInitializer { + + init(Router router, ViewFactory view) { + router.root + ..addRoute( + name: 'add', + path: '/add', + enter: view('add.html')) + ..addRoute( + name: 'recipe', + path: '/recipe/:recipeId', + mount: (Route route) => route + ..addRoute( + name: 'view', + path: '/view', + enter: view('view.html')) + ..addRoute( + name: 'edit', + path: '/edit', + enter: view('edit.html'))); + } +} \ No newline at end of file diff --git a/Chapter_05/recipe_details_component.css b/Chapter_05/recipe_details_component.css new file mode 100644 index 0000000..e69de29 diff --git a/Chapter_05/recipe_details_component.dart b/Chapter_05/recipe_details_component.dart new file mode 100644 index 0000000..0cd56d6 --- /dev/null +++ b/Chapter_05/recipe_details_component.dart @@ -0,0 +1,28 @@ +part of recipe_book; + +@NgComponent( + selector: 'recipe-details', + templateUrl: 'recipe_details_component.html', + cssUrl: 'recipe_details_component.css', + publishAs: 'ctrl', + map: const { + 'recipe-map':'<=>recipeMap' + } +) +class RecipeDetailsComponent implements NgDetachAware { + RouteHandle _route; + Map recipeMap; + Recipe _recipe; + + get recipe { + return recipeMap[_route.parameters['recipeId']]; + } + + RecipeDetailsComponent(RouteProvider routeProvider) { + _route = routeProvider.route; + } + + void detach() { + _route.discard(); + } +} \ No newline at end of file diff --git a/Chapter_05/recipe_details_component.html b/Chapter_05/recipe_details_component.html new file mode 100644 index 0000000..6bff919 --- /dev/null +++ b/Chapter_05/recipe_details_component.html @@ -0,0 +1,19 @@ +
      +

      Recipe Details

      + +
      +
      Name: {{ctrl.recipe.name}}
      +
      Category: {{ctrl.recipe.category}}
      +
      Rating: + +
      +
      +
        +
      • + {{ingredient}} +
      • +
      +
      +
      Directions: {{ctrl.recipe.directions}}
      +
      +
      diff --git a/Chapter_05/recipe_search_component.css b/Chapter_05/recipe_search_component.css new file mode 100644 index 0000000..e69de29 diff --git a/Chapter_05/recipe_search_component.dart b/Chapter_05/recipe_search_component.dart new file mode 100644 index 0000000..8e7c5bc --- /dev/null +++ b/Chapter_05/recipe_search_component.dart @@ -0,0 +1,25 @@ +part of recipe_book; + +@NgComponent( + selector: 'recipe-search', + templateUrl: 'recipe_search_component.html', + cssUrl: 'recipe_search_component.css', + publishAs: 'ctrl', + map: const { + 'name-filter-string': '<=>nameFilterString', + 'category-filter-map' : '<=>categoryFilterMap' + } +) +class RecipeSearchComponent { + String nameFilterString = ""; + Map categoryFilterMap; + + get categories { + return categoryFilterMap.keys.toList(); + } + + void clearFilters() { + categoryFilterMap.keys.forEach((f) => categoryFilterMap[f] = false); + nameFilterString = ""; + } +} \ No newline at end of file diff --git a/Chapter_05/recipe_search_component.html b/Chapter_05/recipe_search_component.html new file mode 100644 index 0000000..3e8cfb0 --- /dev/null +++ b/Chapter_05/recipe_search_component.html @@ -0,0 +1,16 @@ +
      +
      + + +
      +
      + + + {{category}} + +
      + +
      diff --git a/Chapter_05/recipes.json b/Chapter_05/recipes.json new file mode 100644 index 0000000..4bd0e3e --- /dev/null +++ b/Chapter_05/recipes.json @@ -0,0 +1,128 @@ +[ + { + "id":"1", + "name":"Bleu Cheese Stuffed Mushrooms", + "category":"Appetizers", + "ingredients":[ + "12 mushrooms", + "8 oz bleu cheese", + "1/2 red onion, diced", + "1/4 cup bread crumbs", + "1/4 cup parmesan cheese" + ], + "directions":"Preheat oven to 250 degrees. Clean the mushrooms. Break the stems off, chop and set aside. Combine bleu cheese, red onions, bread crumbs and chopped mushroom stems. Fill each mushroom with the bleu cheese mixture and place on a baking sheet. Bake for 20 minutes, or until the tops are golden. Sprinkle with parmesan cheese if desired.", + "rating": 1 + }, + { + "id":"2", + "name":"Cannelini Bean and Mushroom Salad", + "category":"Salads", + "ingredients":[ + "2 cups cannelini", + "a large handful of mushrooms, sliced", + "3 tbsp italian parsley", + "2 tbsp fresh thyme", + "3 tbsp fresh chives", + "a handful of cherry tomatoes, halved", + "slices of parmesan cheese", + "lemon juice", + "olive oil", + "1 garlic clove", + "salt" + ], + "directions":"Cook and drain the beans. Coat mushrooms with olive oil and grill or pan fry them. Combine the beans, mushrooms, herbs and tomatoes. Combine lemon juice, olive oil, garlic and salt and make an emulsion. Pour the dressing over the bean mixture and stir to combine. Use a carrot peeler to peel some parmesan cheese over the top.", + "rating": 3 + }, + { + "id":"3", + "name":"Pumpkin Black Bean Soup", + "category":"Soups", + "ingredients":[ + "2 tablespoon extra-virgin olive oil", + "1 medium onion, finely chopped", + "3 cups canned or packaged vegetable stock, found on soup aisle", + "1 can (14 1/2 ounces) diced tomatoes in juice", + "1 can (15 ounces) black beans, drained", + "2 cans (15 ounces) pumpkin puree", + "1 cup heavy cream", + "1 tablespoon curry powder", + "1 1/2 teaspoons ground cumin", + "1/2 teaspoon cayenne pepper", + "Coarse salt", + "20 blades fresh chives, chopped or snipped, for garnish" + ], + "directions":"Add oil to a soup pot on medium heat. When oil is hot, add onion. Saute onions 5 minutes. Add broth, tomatoes, black beans and pumpkin puree. Stir to combine ingredients and bring soup to a boil. Reduce heat to medium low and stir in cream, curry, cumin, cayenne and salt, to taste. Simmer 5 minutes, adjust seasonings and serve garnished with chopped chives.", + "rating": 3 + }, + { + "id":"4", + "name":"Smoked Salmon Pasta", + "category":"Main Dishes", + "ingredients":[ + "8 ounces spaghetti (or other) pasta", + "1/4 cup pine nuts", + "2 Tbsp olive oil", + "1/3 cup chopped shallots (can substitute onions)", + "2 cloves garlic, minced", + "1/3 cup dry white wine", + "1/4 cup cream", + "2 Tbsp lemon zest", + "1 Tbsp lemon juice", + "2 Tbsp chopped fresh parsley or dill", + "4 ounces smoked salmon, cut into bite sized pieces", + "pinch salt", + "Fresh ground black pepper" + ], + "directions":"Bring a pot of water to a boil over high heat to cook the pasta. Meanwhile, toast the pine nuts in a dry pan or toaster oven and set aside. Add olive oil to a sauce pan on medium heat. Add shallots and cook for 5 minutes until soft and just beginning to caramelize. Add garlic and cook until garlic is soft, but not brown. Add wine and reduce. Turn heat to low and add cream (heat needs to be low, or the cream will curdle). When the pasta is finished cooking, drain it and add to the sauce pan. Turn the heat off and stir to combine. Add lemon juice, parsley or dill, pine nuts, and salmon. Add salt and pepper to taste.", + "rating": 2 + }, + { + "id":"5", + "name":"Pancetta Brussels Sprouts", + "category":"Side Dishes", + "ingredients":[ + "1 lb brussels sprouts", + "1 tbsp olive oil", + "1 tbsp butter", + "1/4 cup pancetta, chopped", + "splash of balsamic vinegar" + ], + "directions":"Wash brussels sprouts, and chop in half. In a pan over medium heat, melt the oil and butter. Add sprouts and pancetta and turn heat to high. Cook until the sprouts are caramelized. Deglaze the pan with a splash of balsamic vinegar.", + "rating": 3 + }, + { + "id":"6", + "name":"Almond Cookies With Chai Spices", + "category":"Desserts", + "ingredients":[ + "1/2 cup unsalted butter, room temperature", + "1 1/3 cups powdered sugar, divided", + "2 tsp vanilla extract", + "1 tsp almond extract", + "3/4 tsp ground allspice", + "3/4 tsp ground cardamom", + "1/2 tsp ground cinnamon", + "1/4 tsp salt", + "1 cup all purpose flour", + "3/4 cup finely chopped toasted almonds" + ], + "directions":"Preheat oven to 350 degrees. Using electric mixer, beat butter, 1/3 cup sugar, both extracts, spices, and salt in medium bowl. Beat in flour, then stir in almonds. Using hands, roll dough into tablespoon-size balls. Place on large baking sheet, spacing apart. Bake until pale golden, about 25 minutes. Cool on sheet 5 minutes. Place remaining sugar in large bowl. Working in batches, gently coat hot cookies in sugar. Cool cookies on rack. Roll again in sugar and serve. ", + "rating": 5 + }, + { + "id":"7", + "name":"Cardamom Poached Pears", + "category":"Desserts", + "ingredients":[ + "2 pears, peeled", + "1 1/4 cups water", + "1/2 cup sugar", + "3 2 inch strips of lemon zest", + "1 cracked whole cardamom", + "A couple grinds of fresh shaved nutmeg", + "vanilla" + ], + "directions":"Combine all ingredients except the pears in a sauce pan and simmer for 10 minutes. Add the pears to the pan and cook, turning the pears occasionally so that all sides cook evenly. Cook for about 10 minutes, or until pears are soft enough to be poked with a fork.", + "rating": 3 + } +] diff --git a/Chapter_05/style.css b/Chapter_05/style.css new file mode 100644 index 0000000..2bd5bb5 --- /dev/null +++ b/Chapter_05/style.css @@ -0,0 +1,28 @@ +.pointer { + cursor: pointer; +} + +.extra-space { + padding-left: 10px; +} + +[ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { + display: none !important; +} + +ul { + list-style-type: none; +} + +#header { + background-color:lightblue; +} +#controls { + background-color:lightgreen; +} +#results { + border: 1px solid red; +} +#details { + border: 1px solid black; +} \ No newline at end of file diff --git a/Chapter_05/view.html b/Chapter_05/view.html new file mode 100644 index 0000000..27cfcc8 --- /dev/null +++ b/Chapter_05/view.html @@ -0,0 +1,6 @@ +
      +View recipe + + + +
      From 306d9d55ac9a6be3c2f0ca834af74b322673b36e Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Thu, 24 Oct 2013 11:35:25 -0700 Subject: [PATCH 16/21] make the query service actually work. clean up code. rename files. --- Chapter_04/index.html | 4 +- Chapter_05/index.html | 67 ++++++++--------- Chapter_05/main.dart | 71 +++++++------------ Chapter_05/query_service.dart | 69 +++++++++++------- Chapter_05/recipe_search_component.css | 0 ...ponent.css => search_recipe_component.css} | 0 ...nent.dart => search_recipe_component.dart} | 8 +-- ...nent.html => search_recipe_component.html} | 0 Chapter_05/style.css | 29 ++++---- Chapter_05/view.html | 6 +- Chapter_05/view_recipe_component.css | 3 + ...ponent.dart => view_recipe_component.dart} | 10 +-- ...ponent.html => view_recipe_component.html} | 6 +- 13 files changed, 135 insertions(+), 138 deletions(-) delete mode 100644 Chapter_05/recipe_search_component.css rename Chapter_05/{recipe_details_component.css => search_recipe_component.css} (100%) rename Chapter_05/{recipe_search_component.dart => search_recipe_component.dart} (74%) rename Chapter_05/{recipe_search_component.html => search_recipe_component.html} (100%) create mode 100644 Chapter_05/view_recipe_component.css rename Chapter_05/{recipe_details_component.dart => view_recipe_component.dart} (59%) rename Chapter_05/{recipe_details_component.html => view_recipe_component.html} (79%) diff --git a/Chapter_04/index.html b/Chapter_04/index.html index f913971..de2a853 100644 --- a/Chapter_04/index.html +++ b/Chapter_04/index.html @@ -7,7 +7,7 @@
      -
      +
      {{ctrl.message}}
      @@ -27,7 +27,7 @@

      Recipe List

      ng-model="ctrl.categoryFilterMap[category]">{{category}}
      - +
      diff --git a/Chapter_05/index.html b/Chapter_05/index.html index 02f13b6..68f504d 100644 --- a/Chapter_05/index.html +++ b/Chapter_05/index.html @@ -5,51 +5,46 @@ +
      + - - -
      -
      - {{ctrl.message}} -
      - - -
      -
      - - - - +
      diff --git a/Chapter_05/main.dart b/Chapter_05/main.dart index 3df7251..466708f 100644 --- a/Chapter_05/main.dart +++ b/Chapter_05/main.dart @@ -2,6 +2,7 @@ library recipe_book; import 'package:angular/angular.dart'; import 'package:angular/routing/module.dart'; +import 'dart:async'; import 'dart:convert'; import 'package:perf_api/perf_api.dart'; import 'package:logging/logging.dart'; @@ -12,8 +13,8 @@ part 'query_service.dart'; part 'rating_component.dart'; part 'recipe.dart'; part 'recipe_book_router.dart'; -part 'recipe_details_component.dart'; -part 'recipe_search_component.dart'; +part 'view_recipe_component.dart'; +part 'search_recipe_component.dart'; @NgDirective( selector: '[recipe-book]', @@ -31,16 +32,14 @@ kitchen and took the recipe book with him!"""; // Determine the initial load state of the app String message = LOADING_MESSAGE; bool recipesLoaded = false; - bool categoriesLoaded = false; + bool categoriesLoaded =false; // Data objects that are loaded from the server side via json - List categories = []; - List recipes = []; - - // get rid of this and replace with a recipe service - Map recipeMap = {}; - - List get foofoo => recipeMap.values.toList(); + List _categories = []; + get categories => _categories; + Map _recipeMap = {}; + get recipeMap => _recipeMap; + get allRecipes => _recipeMap.values.toList(); // Filter box Map categoryFilterMap = {}; @@ -57,46 +56,28 @@ kitchen and took the recipe book with him!"""; } void _loadData() { - recipesLoaded = false; - categoriesLoaded = false; - -// _queryService.loadData(); -// recipesLoaded = _queryService.recipesLoaded; -// categoriesLoaded = _queryService.categoriesLoaded; -// -// if (!recipesLoaded || !categoriesLoaded) { -// message = ERROR_MESSAGE; -// } - - _http.get('/angular.dart.tutorial/Chapter_05/recipes.json') - .then((HttpResponse response) { - for (Map recipe in response.data) { - Recipe r = new Recipe.fromJsonMap(recipe); - recipes.add(r); - recipeMap[r.id] = r; - } + _queryService.getAllRecipes() + .then((Map allRecipes) { + _recipeMap = allRecipes; recipesLoaded = true; - for (Recipe r in recipeMap.values) { - print(r.name); - } }, onError: (Object obj) { recipesLoaded = false; message = ERROR_MESSAGE; }); - _http.get('/angular.dart.tutorial/Chapter_05/categories.json') - .then((HttpResponse response) { - for (String category in response.data) { - categories.add(category); - categoryFilterMap[category] = false; - } - categoriesLoaded = true; - }, - onError: (Object obj) { - categoriesLoaded = false; - message = ERROR_MESSAGE; - }); + _queryService.getAllCategories() + .then((List allCategories) { + _categories = allCategories; + for (String category in _categories) { + categoryFilterMap[category] = false; + } + categoriesLoaded = true; + }, + onError: (Object obj) { + categoriesLoaded = false; + message = ERROR_MESSAGE; + }); } } @@ -108,8 +89,8 @@ main() { var module = new AngularModule() ..type(RecipeBookController) ..type(RatingComponent) - ..type(RecipeSearchComponent) - ..type(RecipeDetailsComponent) + ..type(SearchRecipeComponent) + ..type(ViewRecipeComponent) ..type(CategoryFilter) ..type(QueryService) ..type(RouteInitializer, implementedBy: RecipeBookRouteInitializer) diff --git a/Chapter_05/query_service.dart b/Chapter_05/query_service.dart index 9e4b8a1..427c5ab 100644 --- a/Chapter_05/query_service.dart +++ b/Chapter_05/query_service.dart @@ -4,53 +4,68 @@ class QueryService { String _recipesUrl = '/angular.dart.tutorial/Chapter_05/recipes.json'; String _categoriesUrl = '/angular.dart.tutorial/Chapter_05/categories.json'; - Map _recipes = {}; - List _categories = []; + Future _loaded; - bool _recipesLoaded = false; - bool _categoriesLoaded = false; - Http _http; + Map _recipesCache; + List _categoriesCache; - QueryService(Http this._http); + Http _http; - void loadData() { - _recipesLoaded = false; - _categoriesLoaded = false; + QueryService(Http this._http) { + _loaded = Future.wait([_loadRecipes(), _loadCategories()]); + } - _http.get(_recipesUrl) + Future _loadRecipes() { + return _http.get(_recipesUrl) .then((HttpResponse response) { + _recipesCache = new Map(); for (Map recipe in response.data) { Recipe r = new Recipe.fromJsonMap(recipe); - _recipes[r.id] = r; + _recipesCache[r.id] = r; } - _recipesLoaded = true; + return _recipesCache.length; }, onError: (Object obj) { - _recipesLoaded = false; }); + } - _http.get(_categoriesUrl) + Future _loadCategories() { + return _http.get(_categoriesUrl) .then((HttpResponse response) { - for (String category in response.data) { - _categories.add(category); - } - _categoriesLoaded = true; + _categoriesCache = new List(); + for (String category in response.data) { + _categoriesCache.add(category); + } + return _categoriesCache.length; }, onError: (Object obj) { - _categoriesLoaded = false; }); } - Recipe getRecipeById(String id) { - return _recipes[id]; + Future getRecipeById(String id) { + if (_recipesCache == null) { + return _loaded.then((_) { + return _recipesCache[id]; + }); + } + return new Future.value(_recipesCache[id]); } - List getAllRecipes() { - return _recipes.values.toList(); + Future> getAllRecipes() { + if (_recipesCache == null) { + return _loaded.then((_) { + return _recipesCache; + }); + } + return new Future.value(_recipesCache); } - bool get recipesLoaded => _recipesLoaded; - - bool get categoriesLoaded => _categoriesLoaded; - + Future> getAllCategories() { + if (_categoriesCache == null) { + return _loaded.then((_) { + return _categoriesCache; + }); + } + return new Future.value(_categoriesCache); + } } \ No newline at end of file diff --git a/Chapter_05/recipe_search_component.css b/Chapter_05/recipe_search_component.css deleted file mode 100644 index e69de29..0000000 diff --git a/Chapter_05/recipe_details_component.css b/Chapter_05/search_recipe_component.css similarity index 100% rename from Chapter_05/recipe_details_component.css rename to Chapter_05/search_recipe_component.css diff --git a/Chapter_05/recipe_search_component.dart b/Chapter_05/search_recipe_component.dart similarity index 74% rename from Chapter_05/recipe_search_component.dart rename to Chapter_05/search_recipe_component.dart index 8e7c5bc..f2177ec 100644 --- a/Chapter_05/recipe_search_component.dart +++ b/Chapter_05/search_recipe_component.dart @@ -1,16 +1,16 @@ part of recipe_book; @NgComponent( - selector: 'recipe-search', - templateUrl: 'recipe_search_component.html', - cssUrl: 'recipe_search_component.css', + selector: 'search-recipe', + templateUrl: 'search_recipe_component.html', + cssUrl: 'search_recipe_component.css', publishAs: 'ctrl', map: const { 'name-filter-string': '<=>nameFilterString', 'category-filter-map' : '<=>categoryFilterMap' } ) -class RecipeSearchComponent { +class SearchRecipeComponent { String nameFilterString = ""; Map categoryFilterMap; diff --git a/Chapter_05/recipe_search_component.html b/Chapter_05/search_recipe_component.html similarity index 100% rename from Chapter_05/recipe_search_component.html rename to Chapter_05/search_recipe_component.html diff --git a/Chapter_05/style.css b/Chapter_05/style.css index 2bd5bb5..6c3b1e0 100644 --- a/Chapter_05/style.css +++ b/Chapter_05/style.css @@ -1,11 +1,3 @@ -.pointer { - cursor: pointer; -} - -.extra-space { - padding-left: 10px; -} - [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { display: none !important; } @@ -14,15 +6,24 @@ ul { list-style-type: none; } +a { + text-decoration: none; +} + #header { - background-color:lightblue; } + #controls { - background-color:lightgreen; } -#results { - border: 1px solid red; + +#search-results { + border: 0px solid red; } + #details { - border: 1px solid black; -} \ No newline at end of file + border: 0px solid black; +} + +.extra-space { + padding-left: 10px; +} diff --git a/Chapter_05/view.html b/Chapter_05/view.html index 27cfcc8..bacad89 100644 --- a/Chapter_05/view.html +++ b/Chapter_05/view.html @@ -1,6 +1,4 @@
      -View recipe - - - + +
      diff --git a/Chapter_05/view_recipe_component.css b/Chapter_05/view_recipe_component.css new file mode 100644 index 0000000..391b722 --- /dev/null +++ b/Chapter_05/view_recipe_component.css @@ -0,0 +1,3 @@ +ul { + list-style-type: none; +} diff --git a/Chapter_05/recipe_details_component.dart b/Chapter_05/view_recipe_component.dart similarity index 59% rename from Chapter_05/recipe_details_component.dart rename to Chapter_05/view_recipe_component.dart index 0cd56d6..8a3d41c 100644 --- a/Chapter_05/recipe_details_component.dart +++ b/Chapter_05/view_recipe_component.dart @@ -1,15 +1,15 @@ part of recipe_book; @NgComponent( - selector: 'recipe-details', - templateUrl: 'recipe_details_component.html', - cssUrl: 'recipe_details_component.css', + selector: 'view-recipe', + templateUrl: 'view_recipe_component.html', + cssUrl: 'view_recipe_component.css', publishAs: 'ctrl', map: const { 'recipe-map':'<=>recipeMap' } ) -class RecipeDetailsComponent implements NgDetachAware { +class ViewRecipeComponent implements NgDetachAware { RouteHandle _route; Map recipeMap; Recipe _recipe; @@ -18,7 +18,7 @@ class RecipeDetailsComponent implements NgDetachAware { return recipeMap[_route.parameters['recipeId']]; } - RecipeDetailsComponent(RouteProvider routeProvider) { + ViewRecipeComponent(RouteProvider routeProvider) { _route = routeProvider.route; } diff --git a/Chapter_05/recipe_details_component.html b/Chapter_05/view_recipe_component.html similarity index 79% rename from Chapter_05/recipe_details_component.html rename to Chapter_05/view_recipe_component.html index 6bff919..ba21b5a 100644 --- a/Chapter_05/recipe_details_component.html +++ b/Chapter_05/view_recipe_component.html @@ -8,12 +8,16 @@

      Recipe Details

      + Ingredients:
      • {{ingredient}}
      -
      Directions: {{ctrl.recipe.directions}}
      +
      + Directions: + {{ctrl.recipe.directions}} +
    From 6b003a90daacccfae72751b518b04ef8c3a96886 Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Thu, 24 Oct 2013 11:36:37 -0700 Subject: [PATCH 17/21] adding forgotten pubspec.yaml file --- Chapter_05/pubspec.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 Chapter_05/pubspec.yaml diff --git a/Chapter_05/pubspec.yaml b/Chapter_05/pubspec.yaml new file mode 100644 index 0000000..8b6bc5d --- /dev/null +++ b/Chapter_05/pubspec.yaml @@ -0,0 +1,11 @@ +name: angular_dart_demo +version: 0.0.1 +dependencies: + angular: + # 0.0.2 + git: https://github.com/angular/angular.dart.git + # git: https://github.com/mhevery/angular.dart.git + + browser: any + js: any + unittest: any From 29355fd92d73a3ae03feaca6386032fc137c9d69 Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Thu, 24 Oct 2013 12:00:34 -0700 Subject: [PATCH 18/21] finish hooking all the other views up --- Chapter_05/add.html | 5 +++-- Chapter_05/edit.html | 5 +++-- Chapter_05/search_recipe_component.html | 2 +- Chapter_05/view_recipe_component.html | 4 +++- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Chapter_05/add.html b/Chapter_05/add.html index 62d43e4..77e8db6 100644 --- a/Chapter_05/add.html +++ b/Chapter_05/add.html @@ -1,3 +1,4 @@ -
    -Add recipe +
    +

    Add recipe

    +Now it's your turn. Write some code to add a new recipe
    diff --git a/Chapter_05/edit.html b/Chapter_05/edit.html index a45d43a..17def10 100644 --- a/Chapter_05/edit.html +++ b/Chapter_05/edit.html @@ -1,3 +1,4 @@ -
    -Edit recipe +
    +

    Edit recipe

    + Now it's your turn. Write some code to edit the recipe
    diff --git a/Chapter_05/search_recipe_component.html b/Chapter_05/search_recipe_component.html index 3e8cfb0..edd70e4 100644 --- a/Chapter_05/search_recipe_component.html +++ b/Chapter_05/search_recipe_component.html @@ -12,5 +12,5 @@ ng-model="ctrl.categoryFilterMap[category]">{{category}}
    - +
    diff --git a/Chapter_05/view_recipe_component.html b/Chapter_05/view_recipe_component.html index ba21b5a..f75f677 100644 --- a/Chapter_05/view_recipe_component.html +++ b/Chapter_05/view_recipe_component.html @@ -1,6 +1,8 @@

    Recipe Details

    - + + +
    Name: {{ctrl.recipe.name}}
    Category: {{ctrl.recipe.category}}
    From 71ba68537bb8593484c41d9f788cc4f95b157e3c Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Thu, 24 Oct 2013 12:41:15 -0700 Subject: [PATCH 19/21] doing some final code clean up for Chapter 5 before pushing. --- Chapter_05/add.html | 4 ++-- Chapter_05/main.dart | 6 +----- Chapter_05/style.css | 14 -------------- 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/Chapter_05/add.html b/Chapter_05/add.html index 77e8db6..5c5569c 100644 --- a/Chapter_05/add.html +++ b/Chapter_05/add.html @@ -1,4 +1,4 @@
    -

    Add recipe

    -Now it's your turn. Write some code to add a new recipe +

    Add recipe

    + Now it's your turn. Write some code to add a new recipe
    diff --git a/Chapter_05/main.dart b/Chapter_05/main.dart index 466708f..e1ae9c6 100644 --- a/Chapter_05/main.dart +++ b/Chapter_05/main.dart @@ -5,7 +5,6 @@ import 'package:angular/routing/module.dart'; import 'dart:async'; import 'dart:convert'; import 'package:perf_api/perf_api.dart'; -import 'package:logging/logging.dart'; import 'package:di/di.dart'; part 'category_filter.dart'; @@ -32,7 +31,7 @@ kitchen and took the recipe book with him!"""; // Determine the initial load state of the app String message = LOADING_MESSAGE; bool recipesLoaded = false; - bool categoriesLoaded =false; + bool categoriesLoaded = false; // Data objects that are loaded from the server side via json List _categories = []; @@ -83,9 +82,6 @@ kitchen and took the recipe book with him!"""; // TODO - Remove the Profiler type. It's only needed to get rid of Misko's spam main() { -// Logger.root.level = Level.FINEST; -// Logger.root.onRecord.listen((LogRecord r) { print(r.message); }); - var module = new AngularModule() ..type(RecipeBookController) ..type(RatingComponent) diff --git a/Chapter_05/style.css b/Chapter_05/style.css index 6c3b1e0..f3cf10a 100644 --- a/Chapter_05/style.css +++ b/Chapter_05/style.css @@ -10,20 +10,6 @@ a { text-decoration: none; } -#header { -} - -#controls { -} - -#search-results { - border: 0px solid red; -} - -#details { - border: 0px solid black; -} - .extra-space { padding-left: 10px; } From 80a4c809f6abf2095cc780ebe5539d67d7d854f7 Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Thu, 24 Oct 2013 14:34:39 -0700 Subject: [PATCH 20/21] make a default view route --- Chapter_05/recipe_book_router.dart | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Chapter_05/recipe_book_router.dart b/Chapter_05/recipe_book_router.dart index e425066..e4bc604 100644 --- a/Chapter_05/recipe_book_router.dart +++ b/Chapter_05/recipe_book_router.dart @@ -19,6 +19,11 @@ class RecipeBookRouteInitializer implements RouteInitializer { ..addRoute( name: 'edit', path: '/edit', - enter: view('edit.html'))); + enter: view('edit.html')) + ..addRoute(name: 'view_default', defaultRoute: true, + enter: (_) => + router.go('view', {'recipeId': ':recipeId'}, + startingFrom: route, replace:true))); } -} \ No newline at end of file +} +// TODO add a default route and a redirect example \ No newline at end of file From 9a01360860b56995bbc92be4c25284bd40c61bad Mon Sep 17 00:00:00 2001 From: Tracey Powers Date: Thu, 24 Oct 2013 14:53:47 -0700 Subject: [PATCH 21/21] make a default view route --- Chapter_05/recipe_book_router.dart | 43 +++++++++++++++--------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/Chapter_05/recipe_book_router.dart b/Chapter_05/recipe_book_router.dart index e4bc604..eb7ed95 100644 --- a/Chapter_05/recipe_book_router.dart +++ b/Chapter_05/recipe_book_router.dart @@ -4,26 +4,27 @@ class RecipeBookRouteInitializer implements RouteInitializer { init(Router router, ViewFactory view) { router.root - ..addRoute( - name: 'add', - path: '/add', - enter: view('add.html')) - ..addRoute( - name: 'recipe', - path: '/recipe/:recipeId', - mount: (Route route) => route - ..addRoute( - name: 'view', - path: '/view', - enter: view('view.html')) - ..addRoute( - name: 'edit', - path: '/edit', - enter: view('edit.html')) - ..addRoute(name: 'view_default', defaultRoute: true, - enter: (_) => - router.go('view', {'recipeId': ':recipeId'}, - startingFrom: route, replace:true))); + ..addRoute( + name: 'add', + path: '/add', + enter: view('add.html')) + ..addRoute( + name: 'recipe', + path: '/recipe/:recipeId', + mount: (Route route) => route + ..addRoute( + name: 'view', + path: '/view', + enter: view('view.html')) + ..addRoute( + name: 'edit', + path: '/edit', + enter: view('edit.html')) + ..addRoute( + name: 'view_default', + defaultRoute: true, + enter: (_) => + router.go('view', {'recipeId': ':recipeId'}, + startingFrom: route, replace:true))); } } -// TODO add a default route and a redirect example \ No newline at end of file