Skip to content

Commit 29296f2

Browse files
committed
fix: minor editing points, also usage of let over var
1 parent 61b9569 commit 29296f2

File tree

6 files changed

+60
-52
lines changed

6 files changed

+60
-52
lines changed

index.html

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ <h4 class="exercise-start">
341341

342342
<blockquote>
343343
<p><strong>NOTE</strong>: Notice the back-tick character (`) used with the <code>template</code> property. This character is used to define an <a href="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>&lt;Button text=&quot;Sign in&quot; /&gt;</code>. This is related to the <code>Parse5DomAdapter</code> noted <a href="https://github.com/NativeScript/nativescript-angular/blob/master/README.md#known-issues&quot;">here</a>.</p>
344345
</blockquote>
345346
<p>This code adds two new NativeScript UI elements: a <a href="http://docs.nativescript.org/ApiReference/ui/text-field/how-to.html">text field</a> and a <a href="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>
346347
<ul>
@@ -618,7 +619,7 @@ <h4 class="exercise-start">
618619
<b>Exercise</b>: Two-way data binding with Angular 2
619620
</h4>
620621

621-
<p>In <code>app/app.component.ts</code>, find the find the first <code>&lt;TextField&gt;</code>, and replace it with the <code>&lt;TextField&gt;</code> below, which introduces a new <code>[(ngModel)]</code> attribute:</p>
622+
<p>In <code>app/app.component.ts</code>, find the first <code>&lt;TextField&gt;</code>, and replace it with the <code>&lt;TextField&gt;</code> below, which introduces a new <code>[(ngModel)]</code> attribute:</p>
622623
<pre><code class="lang-XML">&lt;TextField hint=&quot;Email Address&quot; id=&quot;email&quot; keyboardType=&quot;email&quot; [(ngModel)]=&quot;email&quot;
623624
autocorrect=&quot;false&quot; autocapitalizationType=&quot;none&quot;&gt;&lt;/TextField&gt;
624625
</code></pre>
@@ -651,7 +652,7 @@ <h4 class="exercise-start">
651652
</code></pre>
652653
<div class="exercise-end"></div>
653654

654-
<p>The previous examples switches each button’s <code>text</code> attribute from a simple string—e.g. <code>&lt;Button text=&quot;Sign Up&quot;&gt;</code>—to an attribute binding that is dependent on a value defined in the <code>AppComponent</code> class—e.g. <code>&lt;Button [text]=&quot;isLoggingIn ? &#39;Sign in&#39; : &#39;Sign up&#39;&quot;&gt;&quot;</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>&lt;Button text=&quot;Sign Up&quot;&gt;</code>—to an attribute binding that is dependent on a value defined in the <code>AppComponent</code> class—e.g. <code>&lt;Button [text]=&quot;isLoggingIn ? &#39;Sign in&#39; : &#39;Sign up&#39;&quot;&gt;&quot;</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>
655656
<p><img src="images/chapter3/android/4.gif" alt="Text changing on Android">
656657
<img src="images/chapter3/ios/4.gif" alt="Text changing on iOS"></p>
657658
<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">
752753
<b>Exercise</b>: Add an Angular 2 service
753754
</h4>
754755

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>
756757
<pre><code class="lang-TypeScript">import {Injectable} from &quot;angular2/core&quot;;
757758
import {User} from &quot;./user&quot;;
758759

@@ -776,6 +777,9 @@ <h4 class="exercise-start">
776777
})
777778
</code></pre>
778779
<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&#39;s Dependency Injection system, The <a href="http://blog.thoughtram.io/">Thoughtram Blog</a> provides a great 3 parts series on the topic. <a href="http://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular-2.html">Part 1</a>, <a href="http://blog.thoughtram.io/angular/2015/08/20/host-and-visibility-in-angular-2-dependency-injection.html">Part 2 - Host and Visibility</a>, <a href="http://blog.thoughtram.io/angular2/2015/11/23/multi-providers-in-angular-2.html">Part 3 - Multi Providers</a>.</p>
782+
</blockquote>
779783
<p>Next, replace <code>AppComponent</code>’s existing <code>constructor</code> with the code below:</p>
780784
<pre><code class="lang-TypeScript">constructor(private _userService: UserService) {
781785
this.user = new User();
@@ -808,7 +812,7 @@ <h4 class="exercise-start">
808812
</code></pre>
809813
<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>
810814
<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 <a href="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 <a href="https://angular.io/docs/ts/latest/guide/dependency-injection.html">more thorough discussion of the benefits of dependency injection</a>.</p>
812816
<p>Let’s return to our example and make the registration process actually work.</p>
813817
<h4 class="exercise-start">
814818
<b>Exercise</b>: Use an Angular 2 service
@@ -828,7 +832,7 @@ <h4 class="exercise-start">
828832
constructor(private _http: Http) {}
829833

830834
register(user: User) {
831-
var headers = new Headers();
835+
let headers = new Headers();
832836
headers.append(&quot;Content-Type&quot;, &quot;application/json&quot;);
833837

834838
return this._http.post(
@@ -921,7 +925,7 @@ <h4 class="exercise-start">
921925

922926
<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>
923927
<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>
925929
<pre><code class="lang-TypeScript">import {User} from &quot;../../shared/user/user&quot;;
926930
import {UserService} from &quot;../../shared/user/user.service&quot;;
927931
</code></pre>
@@ -976,10 +980,10 @@ <h4 class="exercise-start">
976980
{ path: &quot;/List&quot;, component: ListPage, name: &quot;List&quot; }
977981
])
978982
</code></pre>
979-
<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>
981985
<pre><code class="lang-TypeScript">login(user: User) {
982-
var headers = new Headers();
986+
let headers = new Headers();
983987
headers.append(&quot;Content-Type&quot;, &quot;application/json&quot;);
984988

985989
return this._http.post(
@@ -1002,7 +1006,7 @@ <h4 class="exercise-start">
10021006
<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>
10031007
<pre><code class="lang-TypeScript">import {Router} from &quot;angular2/router&quot;;
10041008
</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>
10061010
<pre><code class="lang-TypeScript">constructor(private _router: Router, private _userService: UserService) {
10071011
</code></pre>
10081012
<p>Finally, replace the <code>LoginPage</code>’s existing <code>login()</code> function with the code below:</p>
@@ -1206,15 +1210,15 @@ <h4 class="exercise-start">
12061210
constructor(private _http: Http) {}
12071211

12081212
load() {
1209-
var headers = new Headers();
1213+
let headers = new Headers();
12101214
headers.append(&quot;Authorization&quot;, &quot;Bearer &quot; + Config.token);
12111215

12121216
return this._http.get(Config.apiUrl + &quot;Groceries&quot;, {
12131217
headers: headers
12141218
})
12151219
.map(res =&gt; res.json())
12161220
.map(data =&gt; {
1217-
var groceryList = [];
1221+
let groceryList = [];
12181222
data.Result.forEach((grocery) =&gt; {
12191223
groceryList.push(new Grocery(grocery.Id, grocery.Name));
12201224
});
@@ -1392,7 +1396,7 @@ <h4 class="exercise-start">
13921396
}
13931397

13941398
// Dismiss the keyboard
1395-
var groceryTextField = &lt;TextField&gt;topmost().currentPage.getViewById(&quot;grocery&quot;);
1399+
let groceryTextField = &lt;TextField&gt;topmost().currentPage.getViewById(&quot;grocery&quot;);
13961400
groceryTextField.dismissSoftInput();
13971401

13981402
this._groceryListService.add(this.grocery)
@@ -1414,7 +1418,7 @@ <h4 class="exercise-start">
14141418
<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>
14151419
<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>
14161420
<pre><code class="lang-TypeScript">add(name: string) {
1417-
var headers = new Headers();
1421+
let headers = new Headers();
14181422
headers.append(&quot;Authorization&quot;, &quot;Bearer &quot; + Config.token);
14191423
headers.append(&quot;Content-Type&quot;, &quot;application/json&quot;);
14201424

@@ -1502,7 +1506,7 @@ <h4 class="exercise-start">
15021506
this.groceryList.unshift(groceryObject);
15031507
});
15041508
this.isLoading = false;
1505-
var groceryList = topmost().currentPage.getViewById(&quot;grocery-list&quot;);
1509+
let groceryList = topmost().currentPage.getViewById(&quot;grocery-list&quot;);
15061510
groceryList.animate({
15071511
opacity: 1,
15081512
duration: 1000
@@ -1643,11 +1647,11 @@ <h4 class="exercise-start">
16431647
</code></pre>
16441648
<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>&lt;ActionItem&gt;</code>&#39;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>
16451649
<pre><code class="lang-TypeScript">share() {
1646-
var list = [];
1647-
for (var i = 0, size = this.groceryList.length; i &lt; size ; i++) {
1650+
let list = [];
1651+
for (let i = 0, size = this.groceryList.length; i &lt; size ; i++) {
16481652
list.push(this.groceryList[i].name);
16491653
}
1650-
var listString = list.join(&quot;, &quot;).trim();
1654+
let listString = list.join(&quot;, &quot;).trim();
16511655
socialShare.shareText(listString);
16521656
}
16531657
</code></pre>
@@ -1688,7 +1692,7 @@ <h4 class="exercise-start">
16881692
declare var NSForegroundColorAttributeName: any;
16891693

16901694
export function setHintColor(args: { view: TextField, color: Color }) {
1691-
var dictionary = new NSDictionary(
1695+
let dictionary = new NSDictionary(
16921696
[args.color.ios],
16931697
[NSForegroundColorAttributeName]
16941698
);
@@ -1703,14 +1707,14 @@ <h4 class="exercise-start">
17031707
</code></pre>
17041708
<p>After that, add the following function to the file’s <code>LoginPage</code> class:</p>
17051709
<pre><code class="lang-TypeScript">setTextFieldColors() {
1706-
var email = &lt;TextField&gt;this.page.getViewById(&quot;email&quot;);
1707-
var password = &lt;TextField&gt;this.page.getViewById(&quot;password&quot;);
1710+
let email = &lt;TextField&gt;this.page.getViewById(&quot;email&quot;);
1711+
let password = &lt;TextField&gt;this.page.getViewById(&quot;password&quot;);
17081712

1709-
var mainTextColor = new Color(this.isLoggingIn ? &quot;black&quot; : &quot;#C4AFB4&quot;);
1713+
let mainTextColor = new Color(this.isLoggingIn ? &quot;black&quot; : &quot;#C4AFB4&quot;);
17101714
email.color = mainTextColor;
17111715
password.color = mainTextColor;
17121716

1713-
var hintColor = new Color(this.isLoggingIn ? &quot;#ACA6A7&quot; : &quot;#C4AFB4&quot;);
1717+
let hintColor = new Color(this.isLoggingIn ? &quot;#ACA6A7&quot; : &quot;#C4AFB4&quot;);
17141718
setHintColor({ view: email, color: hintColor });
17151719
setHintColor({ view: password, color: hintColor });
17161720
}
@@ -1723,7 +1727,7 @@ <h4 class="exercise-start">
17231727
<p>After your app refreshes with this change, you should now see a far more readable hint color:</p>
17241728
<p><img src="images/chapter6/ios/2.png" alt="Better contrast on iOS"></p>
17251729
<p>Let’s back up to the contents of the <code>setHintColor()</code> function so we can discuss what’s going on here.</p>
1726-
<pre><code class="lang-TypeScript">var dictionary = new NSDictionary(
1730+
<pre><code class="lang-TypeScript">let dictionary = new NSDictionary(
17271731
[args.color.ios],
17281732
[NSForegroundColorAttributeName]
17291733
);
@@ -1764,7 +1768,7 @@ <h4 class="exercise-start">
17641768
args.view.android.setHintTextColor(args.color.android);
17651769
}
17661770
if (args.view.ios) {
1767-
var dictionary = new NSDictionary(
1771+
let dictionary = new NSDictionary(
17681772
[args.color.ios],
17691773
[NSForegroundColorAttributeName]
17701774
);
@@ -1823,7 +1827,7 @@ <h4 class="exercise-start">
18231827
<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>
18241828
<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>
18251829
<pre><code class="lang-TypeScript">delete(id: string) {
1826-
var headers = new Headers();
1830+
let headers = new Headers();
18271831
headers.append(&quot;Authorization&quot;, &quot;Bearer &quot; + Config.token);
18281832
headers.append(&quot;Content-Type&quot;, &quot;application/json&quot;);
18291833

src/chapters/chapter2.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ Open `app/app.component.ts` and replace the existing `@Component` with the follo
154154

155155
> **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.
156156
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+
157159
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:
158160

159161
- `<TextField>`

0 commit comments

Comments
 (0)