RSS

The New Router

ראיתי את המצגת של מישקו בנושא ה-router החדש והתאכזבתי.

 

ההרגשה שזה תוכנן ברגע האחרון ולא חשבו מספיק על כל מקרי הקצה של אפליקציות גדולות מאוד.

 

1. באתרים גדולים העץ כל כך גדול שה-URL לא יכול לייצג את ה-PATH של העץ, מגבלת אורך. אני מאמין שזה הסיבה שב- UI Router קראו לזה State ואנחנו יכולנו לקבוע לכל State את ה-Path שלו.

 

2. הרעיון של תיקיות עם "+"  זה נחמד ברוב המקרים, אך יש מקרים שהכל דינאמי והקשר בין ה-URL למבנה התיקיות מאוד מגביל. אני חושב שאנחנו צריכים קובץ מיפוי בין ה-URL לאיפה נמצאים ה- Components.

 

האמת שאני מואד אוהב את ה- UI Router וחשבתי שהם ישפרו אך ישמרו על העקרונות. מקווה שבקרוב נראה גירסה יותר מתקדמת של UI Router לאנגולר 2.0.

 

מה אתם חושבים?

מודעות פרסומת
 
השארת תגובה

פורסם ע"י ב- מאי 7, 2016 ב- Uncategorized

 

Angular 2.0 Component Decorator

 

בפוסט זה אני רוצה להסביר את כל הפרטים הטכנים על @Component.

כאשר אנחנו כותבים באנגולר מחלקה מסוג component אנחנו חייבים להוסיף @Component עם כל הפרטים, כמו למשל selector, template וכ"ו. הפונקציה Component יוצרת מהמידע הנ"ל מחלקה בשם ComponentMetadata ושומרת את המידע כ-metadata על המחלקה.

: Reflect Metadata API

אנגולר 2 משתמש ב-Reflect Metadata כדי לשמור את המידע שנתנו ב- @Component.  כאן אנגולר מגדיר את הפונקציה Component. והפונקציה makeDecorator משתמש ב-Reflect Metadata כדי לאחסן את המידע ביחד עם המחלקה שלכם.

למה זה מעניין?

בעיה: רוצים לרשת מחלקה מסוג Component וגם את הגדרות שלה ב-@Component.

פתרון:

כתבתי decorator חדש , ngExComponent שיכול לקבל arg נוסף של מחלקה. ה- ngExComponentקורא את ה-metadata מהמחלקה וממזג אותם עם ה-metadata של המחלקה היורשת. ראו קוד:

export function ngExComponent(metadata,component?){
   
var
merageMetadata = component?
        Object.assign(getComponentMetadata(component),metadata):
        metadata;
   
return
Component(merageMetadata);
}

 

דוגמא לשימוש:

@Component({
    selector:'users',
    providers:[UserProxy],
    directives: [User],
})
class BaseUser{}
// Derive class
@ngExComponent({     template: `...`
},BaseUser) export class User extends BaseUser{ ... }
 
הסברים:
היתרון בשיטה זו שאני יכול במחלקה BaseUser להגדיר את כל ה-metadata המשותפים לכל סוגי 
ה-User. המחלקה היורשת יכולה לדרוס את ה-metadata שהיא צריכה.
 
לקוחות שלא אוהבים לעבוד עם ngExComponent, אני מוסיף למחלקה העליונה מתודה סטטית
 בשם getMetadata, ראו קוד:
@Component({
    selector:'users',
    providers:[UserProxy],
    dirctives: [User],
})
class BaseUser{
    static getMetadata():ComponentMetadata{
        var result;
        Reflect.getMetadata('annotations', BaseUser)
            .forEach(metadata => {
                if (metadata.constructor.name === 'ComponentMetadata'){
                    result =  metadata;
                }
            });
        return result;
    }
}
 

בעיה: איך משנים בזמן ריצה את ComponentMetadata, כמו למשל templateUrl או styleUrls?

 

פתרון:

אנגולר משתמש בשרותים מסוג Resolvers כדי לקרוא את ה-metadata של Component.

clip_image002

אנחנו יכולים לדרוס את שירותים אלו ואז לעשות מניפולציה על הנתונים לפני שאנגולר משתמש בהם. קראו פוסט שכתבתי בנושא. פתרון זה מאפשר לי להגדיר ל- Component  אחת ומספר views, למשל.

 

אשמח לקבל פידבקים J

נושאים אלו אני מלמד בקורס שלי Angular 2.0 Development לפרטים נוספים לחצו כאן.

 

 
4 תגובות

פורסם ע"י ב- אפריל 21, 2016 ב- Uncategorized

 

Angular 1.x vs. Angular 2.x

תודה לכל האנשים שבאו אתמול ל-meetup. להוריד את הקוד לחצו כאן.

הרצאה זו לקוחה מתוך הקורס שלי על Angular 2.

תאריכים של פתיחת קורס על Angular 2:

1. בחודש מאי 9,16,23,30 (ימי שני ) לינק לרישום, בירושלים.

2. בחודש יוני, 19,22,26,29 בהרצליה.

 
השארת תגובה

פורסם ע"י ב- אפריל 13, 2016 ב- Uncategorized

 

Angular 2.0 ViewResolver Class

אחת השאלות הנפוצות היא, האם אפשר לכתוב פונקציה שמחזירה URL במקום URL סטאטי ב- @Component. באנגולר 1 זה היה אפשרי, ראו פוסט בנושא.

באנגולר 2.0 זה גם אפשרי, אך זה טיפה יותר מסובך.

ראו קוד:

class myViewResolver extends ViewResolver{
    resolve(component: Type): ViewMetadata {       
       
var view =  super
.resolve(component);
       
//
TODO: Write logic here 🙂
       
view.templateUrl = 'app/app.html'
;
       
return
view;
    }
}
bootstrap(App,[
    provide(ViewResolver , {useClass:myViewResolver})
]);

 

הסברים:

אני דורס את ה- ViewResolver הקיים וכותב את שלי שעוטף את הקיים. עטיפה זאת מאפשרת לי לשנות את ה-URL של התבנית ע"פ לוגיקה מסוימת. דוגמאות:

1. להוסיף ל-URL פרמטר של שפה. App.{leng}.html  ה- {leng}  יוחלף בזמן ריצה לשפה המבוקשת.

2. להוסיף ל-URL פרמטר של הרשאה. App.{role}.{leng}.html.

מזכיר לכם שאני יכול להזריק ל- MyViewResolver שרותים אחרים, למשל שרותים שאחראים על שפה והרשאות.

 

מקווה לפגוש אותכם ב-meetup  הקורב שאנ מעביר.

 
תגובה אחת

פורסם ע"י ב- אפריל 6, 2016 ב- Angular 2.0

 

Angular 2.0 Global Decorator

 

בפוסט זה אני רוצה להראות איך אפשר לכתוב @Global Decorator שירשום לנו את ה- Component ל-Injector של האפלקציה.

import {Component, Input, ViewEncapsulation} from 'angular2/core';
import userTpl from './user.tpl.html!text'
;
import userCss from './user.css!text'
;
import {Global} from "../utils/GlobalUtil"
;
@Global()
@Component({
    selector:
'user'
,
    template : userTpl,
    styles:[userCss]
})

export class
UserCmp{
   
private _name:string
;
   
get name(){return this
._name;}
    @Input(
'bp-name'
)
   
set name(val){this
._name = val;}
}

 

ע"י ההוספה של @Global אנחנו יותר לא צריכים לעשות כלום כדי להשתמש ב- UserCmp. להלן הקוד של Global:

import {bootstrap as bp}    from 'angular2/platform/browser';
import
{
provide,
PLATFORM_DIRECTIVES,
PLATFORM_PIPES
}
from "angular2/core";

var providers:any[] = [];

function
addPipe(pipe){
providers.push(provide(PLATFORM_PIPES, {
useValue: [pipe],
multi:
true
}))
}

function
addDirective(directive){
providers.push(provide(PLATFORM_DIRECTIVES, {
useValue: [directive],
multi:
true
}))
}

function
addService(service){
providers.push(service);
}


export function
Global(){
return
(target)=>{

Reflect.getMetadata(
'annotations'
, target)
.forEach(a => {
if( a.constructor.name === 'InjectableMetadata'
){
addService(target);
}
else if (a.constructor.name === 'PipeMetadata'
){
addPipe(target);
}
else
{
addDirective(target);
}
});
return
target;
};
}


export function bootstrap(type,prvs:any
[]){
return
bp(type,providers.concat(prvs));
}

 

 

הסברים:

1. הפונקציה Global רושמת כל Component למערך שאותו אני מכניס ל-Injector של האפלקציה.

2. כדי להריץ את האפלקציה צריך להשתמש ב- bootstrap שאני כתבתי ולא של אנגולר.

 

סיכום:

עבודה בדרך זו מקלה מאוד את הדרך לארוז מספר Components לקובץ אחד, כדי להשתמש ברכיבים אלו כל מה שאתם צריכים זה לטעון את הקובץ. בפוסט הבא אני אראה איך אפשר לדרוס את @Component Decorator כדי לחסוך לאפשר config מרכזי לכל ה- Components.

 

Ng-Course:

הקורס הבא על אנגולר 2.0 מתחיל ביום רביעי ה-6 לחודש. למידע הירשמו כאן.

 
השארת תגובה

פורסם ע"י ב- מרץ 31, 2016 ב- Angular 2.0

 

Angular Injector Round III

בפוסט זה אני מראה איך אפשר לוותר היום על ה- Injector !!! לא נפלתי על הראש (מקווה). בזמן האחרון אני כותב אנגולר 1.x ו-2.0 עם ES 6 או TS, והתחושה שה- Injector פשוט מיותר לגמרי באנגולר 1.0 עם כותבים ב- ES 6.

המטרות של ה- Injector באנגולר 1:

1. הזרקת השירותים שאני רוצה בלי להכיר את המימוש וע"י כך מקל אלי בבדיקות.

2. ה- Injector עובד כ- lazy initialization, עד שלא מבקשים שירות הוא לא נוצר. ראו סרט בנושא.

 

איך מפסיקים להשתמש ב-Injector של אנגולר?

1. בונים תחליף שמשמש כגשר בין השרותים של אנגולר לשרותים שלנו להלן יקרה ngServices.

2. ngServices צריך לתת לי גישה לכל השרותים של אנגולר שהם singleton, שזה כולם חוץ מ- $scope ו- $element. ( אם שכחתי, אנא תעירו לי ).

 // ngServices.js
export var ngServices = {
    $injector : null
};

export function addAngularServices() {
    for(let i = 0; i < arguments.length ; i++){
        let serviceName = arguments[i];
        Object.defineProperty(ngServices,serviceName,{
            get(){
                return ngServices.$injector.get(serviceName);
            }
        });
    }
}

export function ngServicesConfig($injectorProvider){
ngServices.$injector = $injectorProvider.$get();
}

 

 

כאשר אני רוצה לרשום שרות אני משתמש  בפונקציה addAngularServices. השרותים שאני נותן לפונקציה זו חייבים להיות רשומים גם באנגולר.

כאשר רוצים לצרוך שרות עושים import ל- ngServices. ראו דוגמא של שרות userProxy שצורך שרותי אנגולר בסיסיים כמו $http.

Capture

הסברים:

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

כדי ש- ngServices יוכל לצרוך שרותים של אנגולר ולחשוף אותם דרכו את צריכים להוסיף את השורה הבאה למודול הראשי שלכם.

 

import angular from 'angular';
import {ngServicesConfig} from './utils/ngServices'
;

angular.module('app',[])
.config(ngServicesConfig);

 

סיכום:

אני מאמין שברגע שמשתמשים ב-import (systemjs) אין צורך לרשום את השרותים שלנו לתוך המודלים של אנגולר 1. הראתי שזה לא פוגע בשום יכולת קיימית אלה רק מקל אלינו את הפיתוח ומוריד את התלות באנגולר אחד. אני מאמין שזה יקל אלינו גם בשידרוג לאנגולר 2.

 

יש אפשרות לבצע את אותו טריק גם באנגולר 2, אך זה כבר פוסט אחר.

 

צריך לזכור שזה קוד ראשוני ועוד לא עבר את כל הבדיקות לכן אשמח לקבל הערות.

 
2 תגובות

פורסם ע"י ב- מרץ 31, 2016 ב- Uncategorized

 

Angular 2.0 – Relative template and styles URLs

This post will show how to work with systemjs and text plugin to achieve relative template and styles URLs.

Step 1:

Download the SystemJs Text plugin.

Step 2:

For SystemJS use, locate text.js in the application, and then locate it with map configuration:

System.config({

  map: {

    text: 'path/to/text.js'

  }

});

 

Step 3:

Imports the html and css file into the module and then use it in @Component decorator. See code.

import {Component} from 'angular2/core';
import html        from './SubComp.html!text'
;
import css         from './SubComp.css!text'
;

@Component({
selector: 'sub-app',
template: html,
styles  :[css]
})

export class
MyComponent {}

 

 

Summary:

With relative URLs it more easy to organize each Component and it materials (HTML and CSS) in one folder.

If we need to move the folder it will be very easy to do it, without to update the template and styles URLs in the @Component decorator.

 
2 תגובות

פורסם ע"י ב- מרץ 26, 2016 ב- Angular 2.0