RSS

קטגוריה: AngularJS

AngularJS Internals

כבר כמה זמן רץ לי בראש רעיון לכתוב ספר על AngularJS Internals. מטרת הספר להתמקד באיך עובד אנגולר ואיך אפשר לקחת את הידע הזה ולשפר את הקוד שאנחנו כותבים באנגולר, ואפילו קצת את אנגולר עצמו. מסיבה זו יצאתי למסע של כתיבת פוסטים בנושא כדי לראות את התגובות של הקוראים. התגובות שבדר"כ נשלחות אלי למייל מאוד מעודדות ולכן החלטתי להמשיך בנושא ולצעוד לעבר הספר, בלי נדר J

 

רשמית הפוסטים עד כה:

1.      AngularJS Bootstrap

1.1.   AngularJS $injector

1.2.   AngularJS Modules

1.3.   AngularJS Modules Part II

1.4.   AngularJS Module on Demand

1.5.   Angular $provide Services

2.      Directives

2.1.   AngularJS Compile Process

2.2.   AngularJS $animate in Directive

2.3.   Angular Group Validation in ng-repeat

2.4.   Angular Directive Performance

2.5.   Two directives of the same name

2.6.   Controller As vs. $scope

 

מי שרוצה להמשיך לעמיק בנושא מוזמן לקורס שלי ב-14.4.2014 על AngularJS Deep Dive Course.

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

פורסם ע"י ב- מרץ 27, 2014 ב- AngularJS

 

Controller As vs. $scope

 

אחת השאלות הכי שכיחות היא: "למה לי להשתמש ב- Controller as  ולא ב-$scope?"

יש לשאלה הזאת מספר תשובות:

1. מאמר של גון פאפא.

2. תשובתו של מארק, קצת יותר מעמיק.

 

אני רוצה בפוסט זה להסביר לכם מה אני בחרתי ולמה. אני בחרתי ב- Controller As מהסיבה שהקוד יותר נקי ע"פ דעתי ואני יכול יותר בקלות לכתוב JS רגיל עם dependency injection. זה לא אומר שאני לא משתמש ב- $scope בשביל $watch או $apply וכ"ו אך בשביל נתונים (fields) ופעולות (functions) אני עובד על JS רגיל. אני מנסה להשתמש בטכנולוגיה (אנגולר) רק איפה שצריך, ולשמור כמה שיותר על קוד ונילה.

למה?

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

מסקנות:

אני מנסה לכתוב את הקוד האנגולרי בראש הקובץ, יצירת מודול ורישום לתוכו, אך אני לא משתמש ב- anonymous function. הפונקציות נכתבות בחלק התחתון של הקובץ. ראו דוגמא:

 

(function () {

    ////////// Angular Code ////////////

    var app = angular.module('testApp', ['ngRoute']);

    app.factory('proxy', proxyFactory);

    app.controller('Ctrl', Ctrl);

    app.directive('requestForm', requestFormFactory);

    app.directive('responseForm', responseFormFactory);

   

 

    //////////Java Script Code ////////////

 

    function Ctrl($scope, proxy) {}

    function requestFormFactory($scope, proxy, $routeParams) { }

    // …

})();

בנוסף אני מנסה שה- controllers יהיו בעיקר עטיפה ל-BL והשרותים השונים, לצמצם את הקוד שם כמה שאפשר לשרות או מחלקה של JS.

אני מאמין שכתיבה כזו גם מצמצמת את כמות ה- closure וזה דבר טוב, אך מקשה את העבודה עם this צריך לשלוט באיך הוא עובד. בנוסף אני מאמין שכתיבה כזו תוכל לנצל את JS 6.0בצורה יותר נכונה, כאשר הוא יגיע או כאשר אנגולר 2.0 יצא לשוק.

אוקי נחזור לפרטים הקטנים

כאשר אתם כותבים ng-controller="Ctrl as vm" האנגולר יוצר מופעה של Ctrl ע"י פעולת new, כלומר נוצר אוביקט חדש שהוא ה- this ועליו אתם שמים את השדות והמתודות. האוביקט הזה נכנס לתוך המשתנה vm  שמוחזק ע"י ה- $scope.

 

אשמח כמו תמיד לקבל פידבקים או לשמוע מה אתם עושים.

 

 
3 תגובות

פורסם ע"י ב- מרץ 25, 2014 ב- AngularJS

 

AngularJS Modules Part II

בחלק הראשון הבנו איך אנגולר יוצר את $injector והקשר שלו למודולים. המסקנה מחלק זה שאפשר לבנות מודולים שאין בניהם קשר של תלות, כלומר שאתם יוצרים אותם angular.module(name, [] )  הארגומנט השני הוא מערך ריק. את כל התלויות אתם תצתרכו להגדיר ביצירה של המודול המרכזי בלבד. העבודה הכפולה של לשים את קובצי ה-javaScripts על הדף וגם להגדיר אותם במערך התלויות די מעצבן. ראו דוגמאת קוד:

<htmlng-app=”myApp”>

<body>

    <scriptsrc=”angular.js”></script>

    <scriptsrc=”modules/proxies.js”></script>

    <scriptsrc=”modules/bl.js”></script>

    <scriptsrc=”modules/controllers.js”></script>

    <scriptsrc=”modules/directives.js”></script>

    <scriptsrc=”modules/filters.js”></script>

    <script>

        angular.module(‘myApp’, [

            ‘filters’,

            ‘controllers’,

            ‘directives’,

            ‘bl’,

            ‘proxies’

        ]);

    </script>

</body>

</html>

 

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

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

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

 

// app.js file

(function () {

    var app = angular.module('myApp', requiredModules);

 

    // module code.

})();

 

// ngYYY.js file

(function () {

    var ngYYY = angular.module('ngYYY', []);

    requiredModules.push(ngYYY.name);

   

    // module code.

})();

 

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

// ngYYY.js file

(function () {

    var ngYYY = angular.subModule('ngYYY', []);

   

    // module code.

})();

הקוד של app.js נשאר אותו דבר.

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

 
2 תגובות

פורסם ע"י ב- מרץ 21, 2014 ב- AngularJS

 

AngularJS Courses

E4D170

לאור הביקוש הרבה לקורסים על אנגולר אנחנו פותחים קורסים נוספים:

1. AngularJS Workshop for Building Web Appsבתאריכים 2 ו- 9 לאפריל. הקורס מיועד לאנשים שיודעים JavaScript ורוצים להתקדם לפיתוח אפלקציות בווב בטכנולוגית Angular. הקורס בן יומיים שבו נלמד ליישם בפועל פיתוח אפליקצית WEB באמצעות AngularJS, הקורס הינו מעשי הכולל כתיבת קוד ומתקיים בכיתת מחשבים.

2. AngularJS Deep Diveבתאריך 14 למאי. הקורס מיועד למפתחים שעובדים באנגולר ורוצים להבין איך עובד אנגולר ואיך אפשר לשפר את הקוד שלהם שיעבוד יותר מהר.

 
השארת תגובה

פורסם ע"י ב- מרץ 20, 2014 ב- AngularJS

 

AngularJS Modules

אחת השאלות הנפוצות על מודולים זה ע"פ מה מגדירים את התלויות של מודול? הטעות Untitledהנפוצה היא לחשוב שאם מודול משתמש במודול אחר אז יש תלות בניהם, זה לא מדויק. למשל בשפת דוט-נט או גאווה אם אתה מכיר את ה-type אז יש תלות. כאשר מתכננים פתרון רב שכבות ונניח שי לכם את השכבות שבתמונה וכל שכבה היא מודול באנגולר. למשל המודול Controllers מכיל controllers שמכירים אוביקטים או פונקציות ממודול BL, אך זה עדיין לא מגדיר בהכרח קשר של תלות בין המודולים.

אז מה כן ?

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

1. מודולים משמשים רק את $injector ותפקידם מסתיים כאשר ה- $injector נוצר. ראו מתודה createInjector(modulesToLoad). ברגע שה- $injector נוצר כל המידע שרשמתם למודולים השונים מוחזק ב- providerCache, במבנה של אוביקטים עם שדה חובה של $get. ראו פוסטים קודמים על $injector ו- $provide. הקטע הזה בקוד מפעיל את כל מה שרשמתם לתוך המודול ומכניס את זה ל- providerCache.

2. ע"פ סעיף אחד וע"פ המבנה של moduleInstance ( זה מה שאתם מכקבלים שאתם יוצרים מודול, angular.module(name,[]) ) אנחנו מבינים שכל הרישומים שלנו לתוך המודול נשמרים ב- invokeQueue ע"פ הסדר של כתיבת הקוד שלכם חוץ מ- constant שנדחף לראש התור. טעות נפוצה מאוד זה לחשוב שמתודה config מתבצעת אחרי provider וזה לא נכון, זה תלוי בסדר הכתיבה שלכם. ( התיעוד אכן מטעה כאן ).

3. מה שאתם כותבים ב-run מתבצע רק לאחר שמרוקנים את invokeQueue של אותו מודול.

4. שמחברים את סעיפים 1-3 אנחנו מבינים שתהליך טעינה של מודול זה לרוץ על invokeQueue ואחרי זה על runBlocks, מכאן שמה שמגדיר תלות של מודול זה אם אחת הפונקציות שרשומות ב- invokeQueue או ב- runBlocks צריכה שיזריקו לה אובייקט או פונקציה ממודול אחר אז יש תלות. אבל, ויש כאן אבל גדול, אתם חייבים לזכור שכל המתודות הרישום זה למעשה עטיפה של מתודה provider ולא קוראים לפונקצי ה- $get רק עם צריך אותה בשלב ה-run ואלה (Instantiated lazily) ולכן אם למשל במתודה factory היא משתמשת בשרות ממודול אחר זה לא מגדיר תלות בין המודולים, רק אם השתמשתם ב- factory בשלב ה-run של המודול.

5. במתודה provider אי אפשר לקבל שרותים אלה רק את האוביקט עם $get בגלל שהמתודה עובדת על providerInjector ולא על $inject. כמובן שאפשר לתחמן ולהפעיל בכוח את הפונקציה של $get ואז יצרתם תלות.

 

סיכום:

כדי לחסוך בתלויות תשתמשו במתודת ה-run רק במודול המרכזי וכך אתם מבטלים את התלויות בשאר המודולים. כך אני מצליח לבנות מודול config שכולם צורכים ממנו מידע אבל אף אחד לא מגדיר תלות עליו חוץ מהמודול הראשי.

 

מי שמצליח להבין את מה שכתבתי, אשמח לתגובה . מי שלא שיבוא לקורס Angular Deep Dive   וילמד איך בונים תשתיות באנגולר.

 
תגובה אחת

פורסם ע"י ב- מרץ 20, 2014 ב- AngularJS

 

Two directives of the same name

באחד הימים שעברתי על הקוד של Angular ראיתי דבר מוזר, ng-include ו- ng-view כל אחד מהם הוא למעשה שני directives. במילים פשוטות יש שני directives בשם ng-include ואותו דבר גם לגבי ng-view. ראו קוד של ng-view לדגומא. למה? מה קורה כאן? אני אנסה להסביר את הסיבה בפוסט זה.

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

 

1.    שאלה ראשונה: מה משותף לשני ה-directives?

תשובה: שניהם רוצים להחליף את כל ה- element כאשר משתנה ה-url או ה-view. כאשר רוצים להחליף את כל ה- element וה- scope משתמשים בפונקציה $transclude
ובהגדרה transclude: 'element'. להל"ן פסדו קוד התחלתי:

app.directive('myInclude', function ($animate) {

  return {

   transclude: 'element',

   link: function (scope, element, attrs, ctrl, $transclude) {

                       

        // clone the element.

        $transclude(scope, function (clone) {

               $animate.enter(clone, element, element);

        });

    }

  };

});

 

הסברים:

1.     transclude: 'element' מגדיר את כל ה- element ולא רק את הילדים שלו. אם מוציאים את כל ה- element, צריך סימון לאן לחזור ! לכן Angular שם במקום האלמנט הערה. אלמנט הערה זה האלמנט שנקבל בפונקצית ה-link. לדגומא : <– ngView:  !>

2.     פונקצית ה- $transclude מיצרת העתקה של האלמנט עם ה-scope הרצוי, ב- ng-view וב- ng-include ברירת המחדל היא ליצר scope בן.

3.     השרות $animate.enter מכניס את האלמנט המועתק after ה- element. ראו פוסט קודם שלי.


 

2.    שאלת השאלות !!! למה צריך שני directives לאותו directive?

שגיליתי איך Angular מימש את ng-include שאלתי את עצמאי למה הם לא מכניסים לאלמנט את התוכן החדש ואז מקמפלים אותו אם ה- scope הרצוי? (דוגמא בהמשך) למה הם צריכים שני directives?

תשובה:

<div directive1 directive2>

       Hello World…

</div>

אם directive1  מוגדר כמו בסעיף 1, אז אנחנו רוצים ש- directive2 יפעל רק לאחר הפעלת הפונקציה $transclude של directive1, כלומר סדר הפעולות המתבקש של הפעלת ה- link:

1.     שיכפול ה-div ו-scope חדש.

2.     הפעלת ה- directive1 (השני באותו שם), תפקידו לקמפל את התוכן החדש. ראו דוגמא את ngIncludeFillContentDirective.

3.     הפעלת directive2 על האלמנט החדש עם הבנים החדשים.

כדי להשיג את הסדר הזה אנחנו צריכים להגדיר את ה- priority בהתאם:

1.     directive1 למשל 400, כך זה מוגדר ב-ng-include ו- ng-view.

2.     directive2 למשל 0 או כל מספר שקטן מ-400.

3.     directive1 (השני באותו שם) ב- 400-.

 

3. למה directive1 קטן מ- directive2 ומתבצע לפני?

כמו שהסברתי בפוסט על $compile, סדר הפעולות הוא: ( דומה לצורת "V" )

1.    directive 2 preLink

2.    directive 1 preLink

3.    directive 1 postLink (להזכירכם ש-postLink זה link ).

4.    directive 2 postLink


 

4. אז למה אי היה אפשר לכתוב את זה אחרת? למשל:

$transclude(scope, function (clone) {

     clone.html('<b>I am a Template 1 + 3 = {{1+3}}</b>');

     $compile(clone.contents())(scope);

     $animate.enter(clone, elm, elm);

 });
 

הסבר קשה, לא בטוח 100% בתשובה אך אני מאמין שאני צודק J


אם נכתוב את זה כך למעשה שברנו את סדר הפעולות הטבעי של ה-
directives שמתנהג כמו V, כלמור בהתחלה preLink  העדיפות הגבוה ראשונה ובסוף postLink גם העדיפות הגבוהה, באמצע העדיפויות היותר נמוכות. מכאן שדוגמאת הקוד בסעיף 4 תריץ את directive1 ואחרי זה את directive2 וזה לא ההתנהגות הטבעית של directives שאמורה להיות כמו V.

 

סיכום:

 

1.     למדנו שאפשר לכתוב שני directives באותו שם. Angular משתמש בטכניקה זו ב- ng-include וב- ng-view.

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

 

3.     ה- directive1 (השני באותו שם) מקבל את ה- Template שצריך לקמפל דרך ה-controller של ה-directive1 (הראשון( רואים את זה יפה ב-ng-include . כאן ההשמה וכאן הקימפול.

 

אשמח כמו תמיד לקבל פידבקים !!! J

 

נ.ב פתחתי פורום בנושא אנגולר כאן.

 

 

 
השארת תגובה

פורסם ע"י ב- מרץ 16, 2014 ב- AngularJS

 

AngularJS Deep Dive Course

ng-header

בקורס זה נפרק את AngularJS לגורמים שבונים את ה- Framework ונלמד איך עובד AngularJS, מה נקודות החולשה שלו ואיך אפשר לשפר אותו.  הקורס מיועד לאנשים שמכירים AngularJS ועובדים איתו ביום יום, אך לא מכירים איך הוא עובד "מתחת למכסה המנוע". אני מבטיח לכם שתגלו הרבה דברים חדשים.

AngularJS Deep Dive Course

 

HTML is great for declaring static documents, but it falters when we try to use it for declaring dynamic views in web-applications. AngularJS lets you extend HTML vocabulary for your application. The resulting environment is extraordinarily expressive, readable, and quick to develop.

 

AngularJS is a structural framework for dynamic web apps. It lets you use HTML as your template language and lets you extend HTML's syntax to express your application's components clearly and succinctly. Out of the box, it eliminates much of the code you currently write through data binding and dependency injection.

 

Module 1: AngularJS Bootstrap Process

This module gives a quick overview about Angular startup process.

 

clip_image001      Angular Init

clip_image001[1]      Angular Bootstrap

clip_image001[2]      Injector Service

clip_image001[3]      Module Loading process

clip_image001[4]      Lazy Module Loading

clip_image001[5]      $compile service

o   $parse

o   $interpolate

clip_image001[6]      $scope

Module 2: $provide Services Internals

 

clip_image001[7]      Provider Method

clip_image001[8]      Factory Method

clip_image001[9]      Service Method

clip_image001[10]      Value and Constant

clip_image001[11]      Decorator

Module 3: Directive Internals

clip_image001[12]      Directive Definition Object

clip_image001[13]      Directive Execution Order

clip_image001[14]      Compile method vs. Link method

clip_image001[15]      Compile method vs. $compile

clip_image001[16]      Communication between directive

clip_image001[17]      Directive Scope

o   $id

o   $watch and $watchCollection

o   $apply

clip_image001[18]      Directive animations support

clip_image001[19]      Custom Directive Samples:

o   How to build directive with no scope and Watch

o   Dynamic Template

o   Multi Transclusion

clip_image001[20]      Directive Performance tips

Module 4: Communication Services

 

clip_image001[21]      $http Service

o   Headers

o   Transforming Requests & Responses

o   Caching

o   Response Interceptors

clip_image001[22]      $cacheFactory

clip_image001[23]      Angular-Cache module

clip_image001[24]      $resource Service

clip_image001[25]      $q Service

Module 5: Routing and Navigation

 

clip_image001[26]      $location service

clip_image001[27]      ng-view directive

clip_image001[28]      $route service and route object

clip_image001[29]      Navigation flow

clip_image001[30]      Routing broadcasted events

clip_image001[31]      Resolve option and promise

clip_image001[32]      Cancelling route changes

 

Module 6: Forms in AngularJS

 

clip_image001[33]      ng-model binding

clip_image001[34]      ngModelController & ngFormController

o   Input states and css

o   Custom value formatting and parsing

o   Custom validation

o   Custom validation in ng-repeat

clip_image001[35]      Input directive

 
השארת תגובה

פורסם ע"י ב- מרץ 12, 2014 ב- AngularJS