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
+30-26Lines changed: 30 additions & 26 deletions
Original file line number
Diff line number
Diff line change
@@ -341,6 +341,7 @@ <h4 class="exercise-start">
341
341
342
342
<blockquote>
343
343
<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>
344
+
<p><strong>WARNING</strong>: Take special care to properly close all your UI elements and <strong>not</strong> use self-closing declarations like <code><Button text="Sign in" /></code>. This is related to the <code>Parse5DomAdapter</code> noted <ahref="https://github.com/NativeScript/nativescript-angular/blob/master/README.md#known-issues"">here</a>.</p>
344
345
</blockquote>
345
346
<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>
346
347
<ul>
@@ -618,7 +619,7 @@ <h4 class="exercise-start">
618
619
<b>Exercise</b>: Two-way data binding with Angular 2
619
620
</h4>
620
621
621
-
<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>
622
+
<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 clicks the bottom button, Angular is smart enough to update the text of the button automatically. The result looks like this:</p>
655
+
<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 clicks the bottom button, Angular is smart enough to update the text of the button automatically. The result looks like this:</p>
655
656
<p><imgsrc="images/chapter3/android/4.gif" alt="Text changing on Android">
656
657
<imgsrc="images/chapter3/ios/4.gif" alt="Text changing on iOS"></p>
657
658
<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 code 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>
@@ -752,7 +753,7 @@ <h4 class="exercise-start">
752
753
<b>Exercise</b>: Add an Angular 2 service
753
754
</h4>
754
755
755
-
<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>
756
+
<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>
756
757
<pre><codeclass="lang-TypeScript">import {Injectable} from "angular2/core";
757
758
import {User} from "./user";
758
759
@@ -776,6 +777,9 @@ <h4 class="exercise-start">
776
777
})
777
778
</code></pre>
778
779
<p>The <code>providers</code> array is a simple list of all the Angular 2 services that you need to use in your component. At the moment you only have one service, so your <code>providers</code> array only has one entry.</p>
780
+
<blockquote>
781
+
<p><strong>NOTE</strong>: To learn more about the <code>providers</code> array in addition to gaining an in-depth understanding of Angular 2's Dependency Injection system, The <ahref="http://blog.thoughtram.io/">Thoughtram Blog</a> provides a great 3 parts series on the topic. <ahref="http://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular-2.html">Part 1</a>, <ahref="http://blog.thoughtram.io/angular/2015/08/20/host-and-visibility-in-angular-2-dependency-injection.html">Part 2 - Host and Visibility</a>, <ahref="http://blog.thoughtram.io/angular2/2015/11/23/multi-providers-in-angular-2.html">Part 3 - Multi Providers</a>.</p>
782
+
</blockquote>
779
783
<p>Next, replace <code>AppComponent</code>’s existing <code>constructor</code> with the code below:</p>
<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>
810
814
<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>
811
-
<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 for a <ahref="https://angular.io/docs/ts/latest/guide/dependency-injection.html">more thorough discussion of the benefits of dependency injection</a>.</p>
815
+
<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 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>
812
816
<p>Let’s return to our example and make the registration process actually work.</p>
<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>
923
927
<p>First, open <code>app/app.component.ts</code> and copy its contents into <code>app/pages/login/login.component.ts</code>.</p>
924
-
<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>
928
+
<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>
925
929
<pre><codeclass="lang-TypeScript">import {User} from "../../shared/user/user";
926
930
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>
980
-
<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>
983
+
<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>
984
+
<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>
1003
1007
<pre><codeclass="lang-TypeScript">import {Router} from "angular2/router";
1004
1008
</code></pre>
1005
-
<p>Next, replace the current <code>constructor()</code> declaration with the code below, which adds Angular 2’s <code>Router</code> service:</p>
1009
+
<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");
1399
+
let groceryTextField = <TextField>topmost().currentPage.getViewById("grocery");
1396
1400
groceryTextField.dismissSoftInput();
1397
1401
1398
1402
this._groceryListService.add(this.grocery)
@@ -1414,7 +1418,7 @@ <h4 class="exercise-start">
1414
1418
<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>
1415
1419
<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>
1645
1649
<pre><codeclass="lang-TypeScript">share() {
1646
-
var list = [];
1647
-
for (var i = 0, size = this.groceryList.length; i < size ; i++) {
1650
+
let list = [];
1651
+
for (let i = 0, size = this.groceryList.length; i < size ; i++) {
1648
1652
list.push(this.groceryList[i].name);
1649
1653
}
1650
-
var listString = list.join(", ").trim();
1654
+
let listString = list.join(", ").trim();
1651
1655
socialShare.shareText(listString);
1652
1656
}
1653
1657
</code></pre>
@@ -1688,7 +1692,7 @@ <h4 class="exercise-start">
1688
1692
declare var NSForegroundColorAttributeName: any;
1689
1693
1690
1694
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>
1824
1828
<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" />`. This is related to the `Parse5DomAdapter` noted [here](https://github.com/NativeScript/nativescript-angular/blob/master/README.md#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