Skip to content

Commit 834193f

Browse files
committed
Clean up a confusing section in chapter 3, and various other small edits
1 parent 92c5e9a commit 834193f

File tree

5 files changed

+39
-42
lines changed

5 files changed

+39
-42
lines changed

images/chapter2/ios/5.png

3.81 KB
Loading

images/chapter3/android/4.gif

75.9 KB
Loading

images/chapter3/ios/4.gif

71 KB
Loading

index.html

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ <h4 class="exercise-start">
586586

587587
<p>In <code>app/app.component.ts</code> replace the current <code>AppComponent</code> declaration with the one shown below, which adds a new <code>email</code> property, and changes the <code>submit()</code> method to display its value:</p>
588588
<pre><code class="lang-TypeScript">export class AppComponent {
589-
email = &quot;user@nativescript.org&quot;;
589+
email = &quot;nativescriptrocks@telerik.com&quot;;
590590
submit() {
591591
alert(&quot;You’re using: &quot; + this.email);
592592
}
@@ -602,9 +602,9 @@ <h4 class="exercise-start">
602602
<p><img src="images/chapter3/android/1.png" alt="Android with prefilled email">
603603
<img src="images/chapter3/ios/1.png" alt="iOS with prefilled email"></p>
604604
<blockquote>
605-
<p><strong>NOTE</strong>: It’s very easy to confuse Angular 2’s event binding syntax <code>(eventName)=&quot;functionName()&quot;</code> with its attribute binding syntax <code>[attributeName]=&quot;propertyName&quot;</code> 🤔. Don’t worry though; if you get them backwards, the problem is usually easy to debug, as the functionality you’re attempting to add just won’t work. These syntaxes are common enough that you’ll be using them a lot, and eventually you should be able to commit them to memory.</p>
605+
<p><strong>NOTE</strong>: It’s very easy to confuse Angular 2’s event binding syntax <code>(eventName)=&quot;functionName()&quot;</code> with its attribute binding syntax <code>[attributeName]=&quot;propertyName&quot;</code>. Don’t worry though; if you get them backwards, the problem is usually easy to debug, as the functionality you’re attempting to add just won’t work. These syntaxes are common enough that you’ll be using them a lot, and eventually you should be able to commit them to memory.</p>
606606
</blockquote>
607-
<p>This attribute binding approach works really well when you need the data binding to be one way—that is, when you need TypeScript properties, and changes to those properties done in TypeScript code, to appear in the user interface. But in the case of user interface controls that accept user input, such as the text field in this example, usually you need data binding to work two way—that is, you additionally need changes the user makes to be reflected in your TypeScript code.</p>
607+
<p>This attribute binding approach works really well when you need the data binding to be one way—that is, when you need TypeScript properties, and changes to those properties done in TypeScript code, to appear in the user interface. But in the case of user interface controls that accept user input, such as the text field in this example, usually you need data binding to work two way—that is, you additionally need changes the user makes to data via form controls to be reflected in your TypeScript code.</p>
608608
<p>To show that the current example’s data binding is only one way, head back to your app, change the email text field’s value (type a few extra letters or something like that), and then tap the “Sign In” button. Because your <code>submit()</code> function alerts the current value of your component’s <code>email</code> property—<code>alert(&quot;You’re using: &quot; + this.email)</code>—you might expect to see the updated value in the alert. Instead, however, you see the original value. Notice how the typed text and the alert value don’t match in the screenshot below.</p>
609609
<p><img src="images/chapter3/android/2.png" alt="Android with email address that do not match"></p>
610610
<p>To fix this, you need to switch to Angular 2’s two-way data binding syntax.</p>
@@ -621,40 +621,35 @@ <h4 class="exercise-start">
621621
<p>At first glance the <code>[(ngModel)]</code> syntax looks more than a little odd, as it’s essentially a combination of the event and attribute binding syntax that you used in earlier examples. In the case of this example, <code>[(ngModel)]=&quot;email&quot;</code> is shorthand for <code>[text]=&quot;email&quot; (emailChange)=&quot;email=$event&quot;</code>, which binds the email element’s <code>text</code> attribute to an <code>email</code> property and adds a <code>change</code> event handler that updates the <code>email</code> property’s value whenever the user makes a change.</p>
622622
<p>Don’t worry too much about the details here while we’re still getting started. In your head you can think of <code>[(ngModel)]</code> as the way to implement two-way data binding when you need it on form controls. To show that it works, if you again modify your app’s email address and click the “Sign In” button, you’ll see the updated value in the alert as expected:</p>
623623
<p><img src="images/chapter3/android/3.png" alt="Android with email addresses that do match"></p>
624-
<p>At this point, you have a basic login screen setup with two-way data binding—not 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>
625-
<p>Before we tie this app to a backend and make this login screen fully functional, let’s take a step back and setup a structure that can scale.</p>
626-
<!--commenting this out as I don't think it belongs here. We just said we're going to move code out of the single file, then we start talking about more stuff to add to the single file...confuzzled-->
627-
<!--<h4 class="exercise-start">
628-
<b>Exercise</b>: ???
624+
<p>Before we move on, let’s make one additional change to show what else you can do with Angular 2’s data binding APIs. The Groceries app uses the same UI for the “Sign In” form and the “Sign Up” form. Therefore, when the user clicks “Sign Up”, we need to update the text of the buttons (and eventually the functionality that occurs when you tap them). Let’s see how to make that happen.</p>
625+
<h4 class="exercise-start">
626+
<b>Exercise</b>: Using the ternary operator in templates
629627
</h4>
630628

631-
app.component.ts — Replace the two buttons with this
632-
633-
``` XML
634-
<Button [text]="isLoggingIn ? 'Sign in' : 'Sign up'" id="submit-button" (tap)="submit()"></Button>
635-
<Button [text]="isLoggingIn ? 'Sign up' : 'Back to login'" (tap)="toggleDisplay()"></Button>
636-
```
637-
638-
app.component.ts - Use this for the AppComponent class:
639-
640-
``` TypeScript
641-
export class AppComponent {
642-
email = "user@nativescript.org";
629+
<p>Open <code>app/app.component.ts</code> and replace the two existing buttons with the code below:</p>
630+
<pre><code class="lang-XML">&lt;Button [text]=&quot;isLoggingIn ? &#39;Sign in&#39; : &#39;Sign up&#39;&quot; id=&quot;submit-button&quot; (tap)=&quot;submit()&quot;&gt;&lt;/Button&gt;
631+
&lt;Button [text]=&quot;isLoggingIn ? &#39;Sign up&#39; : &#39;Back to login&#39;&quot; (tap)=&quot;toggleDisplay()&quot;&gt;&lt;/Button&gt;
632+
</code></pre>
633+
<p>Next, replace the existing <code>AppComponent</code> declaration with the code below, which adds a new <code>isLoggingIn</code> property, and a new <code>toggleDisplay()</code> method:</p>
634+
<pre><code class="lang-TypeScript">export class AppComponent {
635+
email = &quot;nativescriptrocks@telerik.com&quot;;
643636
isLoggingIn = true;
644637

645638
submit() {
646-
alert("You’re using: " + this.email);
639+
alert(&quot;You’re using: &quot; + this.email);
647640
}
648641
toggleDisplay() {
649642
this.isLoggingIn = !this.isLoggingIn;
650643
}
651644
}
652-
```
653-
645+
</code></pre>
654646
<div class="exercise-end"></div>
655647

656-
TODO: Transition
657-
-->
648+
<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>
649+
<p><img src="images/chapter3/android/4.gif" alt="Text changing on Android">
650+
<img src="images/chapter3/ios/4.gif" alt="Text changing on iOS"></p>
651+
<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>
652+
<p>Before we tie this app to a backend and make this login screen fully functional, let’s take a step back and setup a structure that can scale.</p>
658653
<h3 id="structuring-your-app">Structuring your app</h3>
659654
<p>There are many reasons to segment any application into modular units, and you can <a href="https://en.wikipedia.org/wiki/Modular_programming">read about the various benefits on Wikipedia</a>. Modularizing NativeScript apps, in addition, has one unique benefit: the ability to share the code you write between Angular-2-built web apps, and Angular-2-built native apps.</p>
660655
<p>Even if you have no plans to create an Angular 2 web app, separating out your code is still advantageous for a number of other reasons—testability, ease of maintenance, and so forth—but if you <em>do</em> have plans to build an Angular 2 web app, having a chunk of functionality that you can reuse in your native and web apps can be an invaluable time saver.</p>
@@ -810,7 +805,7 @@ <h4 class="exercise-start">
810805
<p>Create an account, then hardcode those credentials in your constructor to make testing easier:</p>
811806
<pre><code class="lang-TypeScript">constructor(private _userService: UserService) {
812807
this.user = new User();
813-
this.user.email = &quot;user@nativescript.org&quot;;
808+
this.user.email = &quot;nativescriptrocks@telerik.com&quot;;
814809
this.user.password = &quot;password&quot;;
815810
}
816811
</code></pre>
@@ -832,7 +827,7 @@ <h4 class="exercise-start">
832827

833828
constructor(private _userService: UserService) {
834829
this.user = new User();
835-
this.user.email = &quot;user@nativescript.org&quot;;
830+
this.user.email = &quot;nativescriptrocks@telerik.com&quot;;
836831
this.user.password = &quot;password&quot;;
837832
}
838833
submit() {

src/chapters/chapter3.md

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ In `app/app.component.ts` replace the current `AppComponent` declaration with th
5454

5555
``` TypeScript
5656
export class AppComponent {
57-
email = "user@nativescript.org";
57+
email = "nativescriptrocks@telerik.com";
5858
submit() {
5959
alert("You’re using: " + this.email);
6060
}
@@ -75,9 +75,9 @@ The key thing to note here is the `[text]="email"` attribute on the `<TextField>
7575
![Android with prefilled email](images/chapter3/android/1.png)
7676
![iOS with prefilled email](images/chapter3/ios/1.png)
7777

78-
> **NOTE**: It’s very easy to confuse Angular 2’s event binding syntax `(eventName)="functionName()"` with its attribute binding syntax `[attributeName]="propertyName"` 🤔. Don’t worry though; if you get them backwards, the problem is usually easy to debug, as the functionality you’re attempting to add just won’t work. These syntaxes are common enough that you’ll be using them a lot, and eventually you should be able to commit them to memory.
78+
> **NOTE**: It’s very easy to confuse Angular 2’s event binding syntax `(eventName)="functionName()"` with its attribute binding syntax `[attributeName]="propertyName"`. Don’t worry though; if you get them backwards, the problem is usually easy to debug, as the functionality you’re attempting to add just won’t work. These syntaxes are common enough that you’ll be using them a lot, and eventually you should be able to commit them to memory.
7979
80-
This attribute binding approach works really well when you need the data binding to be one way—that is, when you need TypeScript properties, and changes to those properties done in TypeScript code, to appear in the user interface. But in the case of user interface controls that accept user input, such as the text field in this example, usually you need data binding to work two way—that is, you additionally need changes the user makes to be reflected in your TypeScript code.
80+
This attribute binding approach works really well when you need the data binding to be one way—that is, when you need TypeScript properties, and changes to those properties done in TypeScript code, to appear in the user interface. But in the case of user interface controls that accept user input, such as the text field in this example, usually you need data binding to work two way—that is, you additionally need changes the user makes to data via form controls to be reflected in your TypeScript code.
8181

8282
To show that the current example’s data binding is only one way, head back to your app, change the email text field’s value (type a few extra letters or something like that), and then tap the “Sign In” button. Because your `submit()` function alerts the current value of your component’s `email` property—`alert("You’re using: " + this.email)`—you might expect to see the updated value in the alert. Instead, however, you see the original value. Notice how the typed text and the alert value don’t match in the screenshot below.
8383

@@ -104,27 +104,25 @@ Don’t worry too much about the details here while we’re still getting starte
104104

105105
![Android with email addresses that do match](images/chapter3/android/3.png)
106106

107-
At this point, you have a basic login screen setup with two-way data binding—not bad for 20 some lines of code of TypeScript. (Think about how much code you’d have to write in Android Studio _and_ 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.
107+
Before we move on, let’s make one additional change to show what else you can do with Angular 2’s data binding APIs. The Groceries app uses the same UI for the “Sign In” form and the “Sign Up” form. Therefore, when the user clicks “Sign Up”, we need to update the text of the buttons (and eventually the functionality that occurs when you tap them). Let’s see how to make that happen.
108108

109-
Before we tie this app to a backend and make this login screen fully functional, let’s take a step back and setup a structure that can scale.
110109

111-
<!--commenting this out as I don't think it belongs here. We just said we're going to move code out of the single file, then we start talking about more stuff to add to the single file...confuzzled-->
112-
<!--<h4 class="exercise-start">
113-
<b>Exercise</b>: ???
110+
<h4 class="exercise-start">
111+
<b>Exercise</b>: Using the ternary operator in templates
114112
</h4>
115113

116-
app.component.ts — Replace the two buttons with this
114+
Open `app/app.component.ts` and replace the two existing buttons with the code below:
117115

118116
``` XML
119117
<Button [text]="isLoggingIn ? 'Sign in' : 'Sign up'" id="submit-button" (tap)="submit()"></Button>
120118
<Button [text]="isLoggingIn ? 'Sign up' : 'Back to login'" (tap)="toggleDisplay()"></Button>
121119
```
122120

123-
app.component.ts - Use this for the AppComponent class:
121+
Next, replace the existing `AppComponent` declaration with the code below, which adds a new `isLoggingIn` property, and a new `toggleDisplay()` method:
124122

125123
``` TypeScript
126124
export class AppComponent {
127-
email = "user@nativescript.org";
125+
email = "nativescriptrocks@telerik.com";
128126
isLoggingIn = true;
129127

130128
submit() {
@@ -138,10 +136,14 @@ export class AppComponent {
138136

139137
<div class="exercise-end"></div>
140138

141-
TODO: Transition
142-
-->
139+
The previous examples switches each button’s’ `text` attribute from a simple string—e.g. `<Button text="Sign Up">`—to an attribute binding that is dependent on a value defined in the `AppComponent` class—e.g. `<Button [text]="isLoggingIn ? 'Sign in' : 'Sign up'">"`. Now, when the value of the `isLoggingIn` 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:
143140

141+
![Text changing on Android](images/chapter3/android/4.gif)
142+
![Text changing on iOS](images/chapter3/ios/4.gif)
144143

144+
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 _and_ 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.
145+
146+
Before we tie this app to a backend and make this login screen fully functional, let’s take a step back and setup a structure that can scale.
145147

146148
### Structuring your app
147149

@@ -346,7 +348,7 @@ Create an account, then hardcode those credentials in your constructor to make t
346348
``` TypeScript
347349
constructor(private _userService: UserService) {
348350
this.user = new User();
349-
this.user.email = "user@nativescript.org";
351+
this.user.email = "nativescriptrocks@telerik.com";
350352
this.user.password = "password";
351353
}
352354
```
@@ -371,7 +373,7 @@ export class AppComponent {
371373

372374
constructor(private _userService: UserService) {
373375
this.user = new User();
374-
this.user.email = "user@nativescript.org";
376+
this.user.email = "nativescriptrocks@telerik.com";
375377
this.user.password = "password";
376378
}
377379
submit() {

0 commit comments

Comments
 (0)