You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -351,8 +351,6 @@ export class MyComponent implements OnInit {
351
351
map(res=>res.data)
352
352
);
353
353
}
354
-
355
-
}
356
354
}
357
355
```
358
356
@@ -655,170 +653,198 @@ export class CocktailItemComponent {
655
653
656
654
Now if you reload the app and select an ingredient, the app should work as before, but this time you have nice separation of how the Drinks ListView should present each item.
657
655
658
-
### To be continued here!!!!!!!
659
-
660
656
### Components with custom events
661
657
662
-
Adding a custom event to a component is easy. Let's have a look at `LeagueTableComponent` as an example.
663
-
664
-
To make it work we need first to create an `EventEmitter`:
658
+
Adding a custom event - like a `(tap)` event - to a component is easy.<br/>
659
+
This is done by adding an `EventEmitter` property with an `@Output` decorator.
This automatically means that our component, will have an event called `(teamSelected)`, which should be emitting *numbers*. And can be used like this (note that $event will pass the numbers emitted by the event).
### Exercise: Creating a presentation component with @Output
708
+
To create a custom attribute that is capable of both taking data as an input and also updating it, we need to use two-way binding.
701
709
702
-
In this exercise we need to update the app, so that if the user taps on a team in the league table, the app should navigate to `TeamComponent` with `teamId` of that team.
710
+
To do that we need to combine the power of the `@Input` and `@Output` decorators.
703
711
704
-
Even though you could make it happen by adding `[nsRouterLink]` on each team standing, we want the navigation logic to be delegated to the parent component, so it should be the `TablesComponent` that should trigger the navigation.
712
+
Let's imagine we are working on a `ColorPicker` component, which should take a `color`, as an input, but when the user selects a different color, it should provide an updated value.
705
713
706
-
> So in short: when the user taps on a team, we need the `LeagueTableComponent`to emit `teamSelected` with the `teamId`. And the `TablesComponent` should intercept the `teamSelected` event and call `onTeamSelected` where it should navigate to the `TeamComponent`.
714
+
First we need to create a property `@Input color`.
707
715
708
-
<h4 class="exercise-start">
709
-
<b>Exercise</b>: Update LeagueTableComponent with @Output
710
-
</h4>
716
+
Then we need to add a custom event, which is called `propertyNameChange`. For our example we’ll use `@Output() colorChange`.
711
717
712
-
#### Step 1 - Add @Output EventEmitter
718
+
Finally, we need to emit the new value `colorChange.emit(newColor);`
713
719
714
-
Add an `EventEmitter<number>` called `teamSelected` to your `LeagueTableComponent` in `league-table.component.ts`.
### Exercise: Creating a presentation component with @Input @Output
747
+
748
+
In this exercise we need to update the `CocktailsComponent` to replace the first StackLayout that is used for finding an ingredient, and instead use the `SearchComponent`, like this:
749
+
750
+
```XML
751
+
<search-ingredient row="0"
752
+
[(ingredient)]="selectedIngredient"
753
+
(ingredientChange)="updateCocktailList($event)">
754
+
</search-ingredient>
735
755
```
736
756
737
-
<div class="solution-end"></div>
757
+
The `SearchComponent` already contains most of the logic required to load a list of ingredients, and filter them as the user types in the TextField.
738
758
739
-
#### Step 3 - Call OnTeamSelect from the UI
759
+
Your task is to update the `SearchComponent`, so that it allows:
740
760
741
-
Now we need the `ListView` in `league-table.component.html`to call `onTeamSelected` whenever the user taps on one of the teams.
742
-
`ListView` has an event `itemTap` which does precisely that.
761
+
* two way binding to `[(ingredient)]`,
762
+
* emitting selected ingredient via `(ingredientChange)`
743
763
744
-
Add `(itemTap)="onTeamSelected($event)"` to the `ListView`.
764
+
> Hint: Both of these task can be accomplished by adding `@Input()` and `@Output()` to `search.component.ts`. Make sure to also `emit()` ingredients via the emitter.
745
765
746
-
<div class="solution-start"></div>
766
+
<h4 class="exercise-start">
767
+
<b>Exercise</b>: Update LeagueTableComponent with @Output
768
+
</h4>
747
769
748
-
ListView first line
770
+
#### Step 0 - Switch to use SearchComponent
771
+
772
+
You can start by commenting out the code in `cocktails.component.html` that is between:
To create a custom attribute that is capable of both taking data as an input and also updating it, we need to use two-way binding.
814
+
Update the `selectIngredient` function, so that it `emits` the `ingredientChange` event with the `val`.
790
815
791
-
To do that we need to combine the power of the `@Input` and `@Output` decorators.
816
+
<div class="solution-start"></div>
792
817
793
-
Let's imagine we are working on a `ColorPicker` component, which should take a `color`, as an input, but when the user selects a different color, it should provide an updated value.
818
+
``` javascript
819
+
publicselectIngredient(val:string) {
820
+
this.ingredientChange.emit(val);
821
+
}
822
+
```
794
823
795
-
First we need to create a property `@Input color`.
824
+
<div class="solution-end"></div>
796
825
797
-
Then we need to add a custom event, which is called `propertyNameChange`. For our example we’ll use `@Output() colorChange`.
826
+
#### Step 3 - Call selectIngredient from the UI
798
827
799
-
Finally, we need to emit the new value `colorChange.emit(newColor);`
828
+
Now we need the selected `Label` in the ListView in `search.component.html` to call `selectIngredient` whenever the user taps on one of the ingredients.
800
829
801
-
Here is the full code:
830
+
Add `(tap)="selectIngredient(item)"` to the `Label` inside the ListView.
0 commit comments