לתוכן העניינים

    בפרק הקודם התחלנו ללמוד איך יוצרים פרויקט ראשון שיציג לנו תוכן HTML כלשהו, הוספנו את הספריות האלוונטיות, כתבנו קודים בשפת typescript, בסופו של קוד, החלק החשוב (שבו נתמקד היום) היה קובץ שנקרא app.component.ts שבו כתבנו את הקוד הבא:

    Code Snippet
    import { Component } from '@angular/core';

    @Component({
        selector: 'my-app',
        template: '<h1>My First Angular App</h1>'
    })
    export class AppComponent { }

    המאפיין selector גורם לכך שכאשר בדף ה – html יהיה את התוכן <my-app> ייכנס במקומו התוכן שמוגדר על ה – template, ויווצר מופע של המחלקה AppComponent.

     

    בפרק היום נלמד על הדברים הבאים:

    • נראה כיצד להציג תוכן HTML מורכב יותר
    • נוסיף מנגנון של Binding
    • נראה כיצד לאפשר Binding דו כיווני.
    • נעבוד קצת יותר עם מחלקות.

     

    נשנה כרגע את תוכן הקובץ (app.component.ts) לקוד הבא:

    Code Snippet
    import { Component } from '@angular/core';

    @Component({
        selector: 'my-app',
        template: '<h1>{{title}}</h1><h2>{{hero}} details</h2>'
    })
    export class AppComponent {
        title = "Tour of Heroes";
        hero = "Shlomo Goldberg";
    }

     

    למחלקה AppComponent הוספנו שני משתנים (מסוג מחרוזת), אחד בשם title והשני בשם hero.

    שינינו את המאפיין template שיכיל את הערכים הללו בעזרת binding ל – expression על אותם משתנים (מאוד דומה לאנגולר 1), כעת כאשר נרפרש (ונקמפל את הקוד) את המסך נקבל את התוצאה הבאה:

    image

     

    כעת נרחיב קצת את המאפיין hero, במקום שיחזיר משתנה פשוט מסוג מחרוזת, נרצה שיהיה מופע של אובייקט hero, ולכן נוסיף בסוף הקובץ את הקוד הבא:

    Code Snippet
    export class Hero {
        id: number;
        name: string;
    }

     

    כרגע הגדרנו מחלקה חדשה (Object Oriented כבר אמרנו….) בשם Hero אשר מכילה מאפיין השם id ומאפיין בשם name.

    שימו לב לתחביר של typescript, שאת הסוג כותבים אחרי השם תוך שימוש בנקודתיים.

     

    כעת נשנה את המאפיין hero ואת ה – template שנית

    Code Snippet
    @Component({
        selector: 'my-app',
        template: '<h1>{{title}}</h1>' +
        '<h2>{{hero.name}} details</h2>' +
        '<div><label>id: </label>{{hero.id}}</div>' +
        '<div><label>name: </label>{{hero.name}}</div>'
    })
    export class AppComponent {
        title = "Tour of Heroes";
        hero: Hero = {
            id: 1,
            name: "Shlomo Goldberg"
        };
    }

     

    כעת המאפיין hero מכיל מופע של אובייקט מסוג Hero (כמובן שתהיה שגיאת קומפילצייה במידה ונעשה טעויות) וה – template מכיל הרבה יותר מידע (בעזרת binding), התוצאה לאחר קימפול וריענון המסך תהיה כזאת:

    image

     

    כפי שאפשר לראות, כאשר התוכן במאפיין template גולש יותר משורה אחת, זה מתחיל להציק (עם כל השירשורים וסימני הפלוס), ב – typescript יש פיתרון בשם: “Multi-line template strings”, נוכל לכתוב “גרש עקומה” [מופיע בדרך כלל בצד שמאל במקלדת מתחת מקש ה – Esc], הקוד ייראה כך:

    Code Snippet
    template: `
        <h1>{{title}}</h1>
        <h2>{{hero.name}} details</h2>
        <div><label>id: </label>{{hero.id}}</div>
        <div><label>name: </label>{{hero.name}}</div>
    `

    כעת הקוד נקי ומסודר יותר.

     

    אנחנו לקראת הדגמה כיצד כותבים קוד עם קישור דו כיווני, אבל לפני כן נשכלל טיפ טיפה את ה – html. (בתוך ה – template)

    Code Snippet
    template: `
        <h1>{{title}}</h1>
        <h2>{{hero.name}} details</h2>
        <div><label>id: </label>{{hero.id}}</div>
            <div>
            <label>name: </label>
            <input value="{{hero.name}}" placeholder="name" />
        </div>
    `

     

    כעת לאחר קומפילציה וריענון, נקבל את התוצאה הבאה:

    image

     

    כמובן שזה עדיין קישור לכיוון אחד (מתוך ה – ts לתצוגה), אבל לפני שנתקדם לקישור דו כיווני נרצה להבין כיצד לתחזק בצורה קלה את בקוד, ודי ברור שגם עם השימוש ב – Multi-line template strings כאשר התוכן קצת גודל זה לא בדיוק הדרך הכי נוחה לעבודה.

    ולכן במקום להשתמש עם template נעבור להשתמש עם templateUrl, הקוד ייראה כך:

    Code Snippet
    @Component({
        selector: 'my-app',
        templateUrl: './app/app.component.html'
    })

    כאשר המאפיין templateUrl מקבל נתיב לקובץ שמכיל את התוכן המוצג (הנתיב חייב להיות אבסולוטי, בהמשך נלמד כיצד לשנות זאת)

    נוסיף תחת תיקיית app קובץ בשם app.component.html, ונעתיק את התוכן שהיה במאפיין template לשם.

    Code Snippet
    <h1>{{title}}</h1>
    <h2>{{hero.name}} details</h2>
    <div><label>id: </label>{{hero.id}}</div>
    <div>
        <label>name: </label>
        <input value="{{hero.name}}" placeholder="name" />
    </div>

    די ברור שהקוד הרבה יותר קריא וברור.

     

    כדי לתמוך בקישור דו כיווני (Two-Way Binding), נצטרך שני דברים, האחד להוסיף ל – app.module.ts במאפיין imports את FormsModule (תפקידו לעבוד עם טפסים), כמובן שלפני שנוכל לעשות זאת נצטרך בתחילת הקובץ לייבא אותו (שימוש ב – import מ – angular/forms), הקובץ ייראה כך:

    Code Snippet
    import { NgModule } from "@angular/core";
    import { BrowserModule } from "@angular/platform-browser";
    import { FormsModule } from '@angular/forms';
    import { AppComponent } from "./app.component";

    @NgModule({
        imports: [BrowserModule, FormsModule],
        declarations: [AppComponent],
        bootstrap: [AppComponent]
    })
    export class AppModule {

    }

     

    למעשה, ניתן להבין שכל מודול גלובלי שנצטרך אותו בכל המערכת (כגון עבודה עם טפסים) נוכל להוסיף את הרישום אליו בקובץ זה.

    כעת נוכל לשנות את התוכן בקובץ app.component.html לשימוש עם ngModel, כך:

    Code Snippet
    <h1>{{title}}</h1>
    <h2>{{hero.name}} details</h2>
    <div><label>id: </label>{{hero.id}}</div>
    <div>
        <label>name: </label>
        <input [(ngModel)]="hero.name" placeholder="name" />
    </div>

     

    שימו לב כיצד כותבים ngModel, עם סוגריים מרובעות ועגולות. (אולי נדבר על הסיבה לכך באחד מהפוסטים הבאים)

    כעת כאשר נריץ ונשנה את התוכן בתיבת הטקסט, ישתנה התוכן גם בחלק העליון במסך.

    image