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
Copy file name to clipboardExpand all lines: index.html
+35-26Lines changed: 35 additions & 26 deletions
Original file line number
Diff line number
Diff line change
@@ -353,6 +353,7 @@ <h4 class="exercise-start">
353
353
354
354
<blockquote>
355
355
<p><strong>NOTE</strong>: Notice the back-tick character (`) used with the <code>template</code> property. This character is used to define an <ahref="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals">ES2015 template literal</a>, which TypeScript supports, and which allows you to write multi-line strings without using messy string concatenation.</p>
356
+
<p><strong>WARNING</strong>: Take special care to properly close all your UI elements and <em>not</em> use self-closing declarations like <code><Button text="Sign in" /></code>. The limitation is related to the <ahref="https://github.com/inikulin/parse5">parse5 library</a> Angular 2 uses to parse templates, and you can read <ahref="https://github.com/NativeScript/nativescript-angular#known-issues">details about the issue on GitHub</a>.</p>
356
357
</blockquote>
357
358
<p>This code adds two new NativeScript UI elements: a <ahref="http://docs.nativescript.org/ApiReference/ui/text-field/how-to.html">text field</a> and a <ahref="http://docs.nativescript.org/ApiReference/ui/button/how-to.html">button</a>. Much like HTML elements, NativeScript UI elements provide attributes to let you configure their behavior and appearance. The code you just added uses the following attributes:</p>
358
359
<ul>
@@ -634,7 +635,7 @@ <h4 class="exercise-start">
634
635
<b>Exercise</b>: Two-way data binding with Angular 2
635
636
</h4>
636
637
637
-
<p>In <code>app/app.component.ts</code>, find the find the first <code><TextField></code>, and replace it with the <code><TextField></code> below, which introduces a new <code>[(ngModel)]</code> attribute:</p>
638
+
<p>In <code>app/app.component.ts</code>, find the first <code><TextField></code>, and replace it with the <code><TextField></code> below, which introduces a new <code>[(ngModel)]</code> attribute:</p>
<p>The previous examples switches each button’s’<code>text</code> attribute from a simple string—e.g. <code><Button text="Sign Up"></code>—to an attribute binding that is dependent on a value defined in the <code>AppComponent</code> class—e.g. <code><Button [text]="isLoggingIn ? 'Sign in' : 'Sign up'">"</code>. Now, when the value of the <code>isLoggingIn</code> attributes changes after the user taps the bottom button, Angular is smart enough to update the text of the button automatically. The result looks like this:</p>
671
+
<p>The previous examples switches each button’s <code>text</code> attribute from a simple string—e.g. <code><Button text="Sign Up"></code>—to an attribute binding that is dependent on a value defined in the <code>AppComponent</code> class—e.g. <code><Button [text]="isLoggingIn ? 'Sign in' : 'Sign up'">"</code>. Now, when the value of the <code>isLoggingIn</code> attributes changes after the user taps the bottom button, Angular is smart enough to update the text of the button automatically. The result looks like this:</p>
671
672
<p><imgsrc="images/chapter3/android/4.gif" alt="Text changing on Android">
672
673
<imgsrc="images/chapter3/ios/4.gif" alt="Text changing on iOS"></p>
673
674
<p>At this point, you have a basic login screen setup with two-way data binding—which isn’t bad for 20 some lines of TypeScript. (Think about how much code you’d have to write in Android Studio <em>and</em> Xcode to accomplish the same task.) To this point though you’ve been placing all of your logic in a single TypeScript file, which doesn’t scale all that well for real-world applications.</p>
@@ -772,7 +773,7 @@ <h4 class="exercise-start">
772
773
<b>Exercise</b>: Add an Angular 2 service
773
774
</h4>
774
775
775
-
<p>There’s are several new concepts to introduce with Angular services, so we’re going to start by stubbing out a new <code>register()</code> method, and then come back to the implementation later in this section. With that in mind, open <code>app/shared/user/user.service.ts</code> and paste in the following code:</p>
776
+
<p>There are several new concepts to introduce with Angular services, so we’re going to start by stubbing out a new <code>register()</code> method, and then come back to the implementation later in this section. With that in mind, open <code>app/shared/user/user.service.ts</code> and paste in the following code:</p>
776
777
<pre><codeclass="lang-TypeScript">import {Injectable} from "angular2/core";
777
778
import {User} from "./user";
778
779
@@ -828,7 +829,15 @@ <h4 class="exercise-start">
828
829
</code></pre>
829
830
<p>This is Angular 2’s dependency injection implementation in action. Because you registered <code>UserService</code> as a provider in this component’s <code>providers</code> array, when Angular sees this syntax it creates an instance of the <code>UserService</code> class, and passes that instance into the component’s constructor.</p>
830
831
<p>This begs a bigger question though: why bother with all of this? Why not run <code>this._userService = new UserService()</code> in the component’s constructor and forget the complexity of <code>@Injectable</code> and <code>providers</code>?</p>
831
-
<p>The short answer is a dependency-injection-based approach to coding keeps your classes less coupled, and therefore more maintainable and testable as your application evolves over time. For a longer answer, head over to the Angular’s docs for a <ahref="https://angular.io/docs/ts/latest/guide/dependency-injection.html">more thorough discussion of the benefits of dependency injection</a>.</p>
832
+
<p>The short answer is a dependency-injection-based approach to coding keeps your classes less coupled, and therefore more maintainable and testable as your application evolves over time. For a longer answer, head over to the Angular’s docs for a <ahref="https://angular.io/docs/ts/latest/guide/dependency-injection.html">thorough discussion of the benefits of dependency injection</a>.</p>
833
+
<blockquote>
834
+
<p><strong>NOTE</strong>: If you’re looking to learn more about Angular 2’s <code>providers</code> array and dependency injection implementation, the <ahref="http://blog.thoughtram.io/">thoughtram blog</a> has a great 3-part series that covers the topic in more detail than this guide.</p>
<li><ahref="http://blog.thoughtram.io/angular/2015/08/20/host-and-visibility-in-angular-2-dependency-injection.html">Part 2—Host and Visibility</a></li>
<p>To this point you’ve been putting your login page code in <code>app.component.ts</code>. Let’s move that logic into the <code>pages/login</code> folder to make room for additional pages.</p>
943
952
<p>First, open <code>app/app.component.ts</code> and copy its contents into <code>app/pages/login/login.component.ts</code>.</p>
944
-
<p>Next, in <code>login.component.ts</code>, change the name of the class from “AppComponent” to “LoginPage, and update the two paths below accordingly:</p>
953
+
<p>Next, in <code>login.component.ts</code>, change the name of the class from “AppComponent” to “LoginPage”, and update the two paths below accordingly:</p>
945
954
<pre><codeclass="lang-TypeScript">import {User} from "../../shared/user/user";
946
955
import {UserService} from "../../shared/user/user.service";
<p>Angular 2 now knows about the list page, but we still need to navigate the user to that page at the appropriate time. Our next step is to allow users to log into their accounts, and to take navigate them to the new list page after they successfully authenticate.</p>
1000
-
<p>To do that, start by opening <code>app/shared/user/user.service.ts</code> and the <code>login()</code> function below to the existing <code>UserService</code> class:</p>
1008
+
<p>Angular 2 now knows about the list page, but we still need to navigate the user to that page at the appropriate time. Our next step is to allow users to log into their accounts, then navigate them to the new list page after they have successfully authenticated.</p>
1009
+
<p>To do that, start by opening <code>app/shared/user/user.service.ts</code> and add the <code>login()</code> function below to the existing <code>UserService</code> class:</p>
<p>To use this <code>login()</code> function, return to <code>app/login/login.component.ts</code>, and add the following import to the top of the file:</p>
1023
1032
<pre><codeclass="lang-TypeScript">import {Router} from "angular2/router";
1024
1033
</code></pre>
1025
-
<p>Next, replace the current <code>constructor()</code> declaration with the code below, which adds Angular 2’s <code>Router</code> service:</p>
1034
+
<p>Next, replace the current <code>constructor()</code> declaration with the code below, which injects Angular 2’s <code>Router</code> service:</p>
var groceryTextField = <TextField>topmost().currentPage.getViewById("grocery");
1424
+
let groceryTextField = <TextField>topmost().currentPage.getViewById("grocery");
1416
1425
groceryTextField.dismissSoftInput();
1417
1426
1418
1427
this._groceryListService.add(this.grocery)
@@ -1434,7 +1443,7 @@ <h4 class="exercise-start">
1434
1443
<p>In this function you first ensure the user didn’t submit without typing a grocery. If the user did type something, you dismiss the device’s keyboard with the TextField element’s <code>dismissSoftInput()</code> method, and then call a new <code>add()</code> method on the <code>GroceryListService</code>.</p>
1435
1444
<p>To finish this example you have to define that new <code>add()</code> method. To do so, open <code>app/shared/grocery/grocery-list.service.ts</code> and paste the following function into the <code>GroceryService</code> class:</p>
<p>Finally, now that you’ve installed and required the plugin, and setup a UI to use it, your last step is implementing the <code><ActionItem></code>'s <code>tap</code> handler. Open <code>app/pages/list/list.component.ts</code> again and add the following function to the <code>ListPage</code> class:</p>
1665
1674
<pre><codeclass="lang-TypeScript">share() {
1666
-
var list = [];
1667
-
for (var i = 0, size = this.groceryList.length; i < size ; i++) {
1675
+
let list = [];
1676
+
for (let i = 0, size = this.groceryList.length; i < size ; i++) {
1668
1677
list.push(this.groceryList[i].name);
1669
1678
}
1670
-
var listString = list.join(", ").trim();
1679
+
let listString = list.join(", ").trim();
1671
1680
socialShare.shareText(listString);
1672
1681
}
1673
1682
</code></pre>
@@ -1708,7 +1717,7 @@ <h4 class="exercise-start">
1708
1717
declare var NSForegroundColorAttributeName: any;
1709
1718
1710
1719
export function setHintColor(args: { view: TextField, color: Color }) {
<p>As cool as Groceries is, it’s currently missing one crucial feature for a grocery management app: the ability to delete groceries from the list.</p>
1844
1853
<p>The Groceries backend already supports deleting, but it’s up to you to implement the feature in the app. You do get two hints though. First, this is a function you can use in the <code>GroceryListService</code> for performing the necessary HTTP call to delete a grocery:</p>
Copy file name to clipboardExpand all lines: src/chapters/chapter2.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -154,6 +154,8 @@ Open `app/app.component.ts` and replace the existing `@Component` with the follo
154
154
155
155
> **NOTE**: Notice the back-tick character (\`) used with the `template` property. This character is used to define an [ES2015 template literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals), which TypeScript supports, and which allows you to write multi-line strings without using messy string concatenation.
156
156
157
+
> **WARNING**: Take special care to properly close all your UI elements and _not_ use self-closing declarations like `<Button text="Sign in" />`. The limitation is related to the [parse5 library](https://github.com/inikulin/parse5) Angular 2 uses to parse templates, and you can read [details about the issue on GitHub](https://github.com/NativeScript/nativescript-angular#known-issues).
158
+
157
159
This code adds two new NativeScript UI elements: a [text field](http://docs.nativescript.org/ApiReference/ui/text-field/how-to.html) and a [button](http://docs.nativescript.org/ApiReference/ui/button/how-to.html). Much like HTML elements, NativeScript UI elements provide attributes to let you configure their behavior and appearance. The code you just added uses the following attributes:
0 commit comments