RSS

Master Template in AngularJS

14 פבר

Master Template in AngularJS

 

אנגולר מאפשר לנו לכתוב תבניות מאוד חכמות, וע"י Directives אנחנו יכולים לארוז אותם לתוך תג. למשל בדוגמא של accordion ו- expander, התוצאה הסופית היא שזה מתורגם לHTML מאוד גדול ביחס לתבנית.

<accordion>

   <h1>Eyal – {{date}}</h1>

   <expander class='expander'

             ng-repeat='item in expanders'

             expander-title='{{item.title}}'>

        {{item.text}}

   </expander>

</accordion>

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

דוגמאות למצבים שאני חושב שגישה זו עושה הגיון.

דוגמא 1: Binding Once or Not

תבנית עם Binding Once שלפעמים אני רוצה לבטל את ה- Binding Once. למשל התבנית הבאה:

clip_image002כאשר אני מסתכל על רשימה של פריטים אני רוצה שהתבנית של המוצר תיהיה עם יכולות של Binding Once ואילו כשאני מסתכל על מוצר בודד אני רוצה שאותה תבנית תיהיה Two way Data-binding. כלומר ההבדל היחידי בין התבניות זה ה- "::" שצריך להוסיף לפני שם המשתנה כדי לקבל binding once {{expression::}}. זה מקרה קלאסי לבנות Master Template שיקבע עם יהיה לפני שם המשנה ה-"::" או לא ע"י פרמטר.

 

דוגמא 2: שפות

כאשר אנחנו רוצים תמיכה של שפות בתוך התבניות אפשר להשתמש ב- angular-translate. אבל אפשר גם להשתמש בפתרון של Master Template ואז אנגולר יעבוד פחות קשה וגם יהיה יותר קל להבין את התבניות.

מה משותף לשתי הדוגמאות האלו? שה-MT יכול להכין את התבניות ע"פ מידע שקיים בזמן "קימפול" ואנגולר עובד על התבניות שנוצרו בזמן ריצה. ראו שרטוט.

clip_image004

אם לא רוצים להכין מראש את התבניות ע"פ שפה, אפשר להעביר את ה-MT לצד השרת ואז להוסיף ל-URL ערך שמציין את השפה הרצויה. ( לדוגמא : http://evardi.com/product.html?lag=heb  ) פתרון לגישה זו פרסמתי בפוסט AngularJS Tips 1–Directive TemplateURL.

כאשר לא רוצים לערב את השרת, אפשר לעשות אותו דבר בצד של אנגולר.

השאלה שמתעוררת היא  באיזה טכנולוגיה נשתמש כדי ליצור את התבניות של אנגולר? אפשר handlebars למשל, אבל למה לא להשתמש בפתרון ש- EcmaScript 6.0 מביא לשולחן?

לדוגמא:

(function (angular) {
"use strict"
;
///////////// AngularJS Code ///////
var mi = angular.module('myApp'
, [])
.factory(
'lang'
,langFactory)
.directive(
'helloWorld'
,helloWorldDirective);

function langFactory(){
return
{
he:{ hello : "
שלום" },
en :{ hello : "hello"
}
};
}

function helloWorldDirective(lang,$log){
return
{
template :
function
($compileNode, templateAttrs){
var
template = `<div>
<b> ${lang.he.hello}<b> : {{
name}}

                  </div>`;
return template.toString();
}
};
}
})(
angular
);

 

הסברים:

כאשר אנגולר מקמפל קטע HTML והוא מזהה את הדיראקטיב hello-world הוא קורא ל-template. ואז נוצרת תבנית עם השפה הרצויה שאותה אנגולר מקמפל. הבעיה שאם הדיראקטיב נמצא מספר פעמים על הדף הפונקציה של template תקרא מספר פעמיים. לכן צריך להוסיף מנגנון של Chace. אם חושבים על זה פעם שניה אפשר בשלב ה-run לעבד את התבניות ולהכניס אותם ל- $templateChaceואז הדראקטייב לא צריך פונקציה מיוחדת ואפשר לחזור לעבוד עם templateUrl.

 

דוגמא:

(function (angular) {
    "use strict";
    ///////////// AngularJS Code ///////
    var mi = angular.module('myApp', [])
        .factory('lang',langFactory)
        .directive('helloWorld2',helloWorldDirective2)
        .run(function($templateCache,lang){
            var template = `<div>
            <b> ${lang.he.hello}<b> : {{name}}
            </div>`;
            $templateCache.put("helloworld.html",template.toString());
        });
    function langFactory(){
        return{
          he:{ hello : "שלום" },
          en :{ hello : "hello" }
        };
    }
    function helloWorldDirective2(lang,$log){
        return{
            templateUrl : "helloworld.html"
        };
    }
})(angular);
 
הסברים:
בשלב העלייה של אנגולר אנחנו בונים את התבניות ומכניסים להם את התרגומים. 
כמובן שאפשר להמשיך לשפר את המנגנון ולעבוד עם קבצים, לעבד אותם ואז להכניס אותם 
ל-$templateCache. אני אישית חושב שצריך לבצע את זה בצד השרת, הכי טוב מבחינת ביצועים.
 
דוגמא 3:
יש הרבה דיראקטייב שהם statics, כלומר הם מקבלים דרך ה- attributes ערכים קבועים כלומר 
אי אפשר לחבר את ה-attributes האלה ל-data binding ואז הם מוחלפים בתבנית. 
כלומר הערכים של ה- attributesנקבעים בזמן כתיבת ה-HTML.

למשל:
<image-button img="face.jpg" imgAlign="left">
    Hello World
</image-button>
 
הדיראקטייב הזה מיצר כפתור שבנוי מתמונה וטקסט ואפשר לקבוע עם התמונה תהייה באחד 
מהצדדים ימין, שמאל, למטה או למעלה. הדראקטייב הזה הואstatic  הוא נועד רק כדי לחסוך 
שורות קוד ב- HTML. 
 
דארקטייב כזה מאוד קל כאשר כותבים אותו באנגולר בצורה נאיבית. הבעיה שמהר מאוד י
וצרים scope ו- watchים, דברים אלו יוצרים בעיות ביצועים שלא לצורך.
 
פתרון:
 
function imageButtonDirective($log){
    return{
        template : function($compileNode, attrs){
            var template = `<div>
            <img src=${attrs.img} align=${attrs.imgalign}/>
            ${$compileNode.html()}
            </div>`;
            $log.debug(template.toString());
            return template.toString();
        }
    };
}
 
כאשר אנחנו בונים את התבנית ב- template אנחנו מקבלים מספר יתרונות:
1. שימוש בדראקטייב זה ב- ng-repeat הפונקציה ליצירת התבנית תופעל רק פעם אחת. שימו לב, 
אפשר לעשות את זה גם במתודה compile, אך יש בזה שתי חסרונות:
A.      אי אפשר להוסיף דראקטייב בשלב ה- compile בלי לקמפל שוב את התבנית עם $compile.
B.      קידוד תבניות הרבה יותר נוח בשיטה declarative מאשר בשיטה של imperative.
2. אפשר לעבוד עם Chace ע"פ הערכים שמקבלים ב- attributes ולכן מקבלים ביצועים טובים יותר.
3. גם במקרה הזה אפשר היה לעבד את המידע בצד השרת ואפילו להשתמש בתוכנה כמו grant כלומר 
לבצע את העיבוד בזמן ה- build.
 
סיכום:
החיים הם לא שחור או לבן, יש הרבה מאוד אפור...
במקרים מסוימים כאשר אפשר לעבד את ה-HTML בזמן ה-build עדיף לא להשתמש בטכנולוגית 
האנגולר כי נשלם על זה בביצועים שלא לצורך.
 
אשמח לקבל תגובות !!!
 
אם אהבתם את הפוסט ואתם רוצים להמשיך ולהעמיק בנושא, אשמח לראות אותם בקורס 
שלי על אנגולר למתקדמים.

 

 

 

מודעות פרסומת
 
2 תגובות

פורסם ע"י ב- פברואר 14, 2015 ב- AngularJS, AngularJS Tips

 

2 תגובות ל-“Master Template in AngularJS

  1. noname

    פברואר 16, 2015 at 3:54 am

    next time write in english

     
  2. עמית

    מאי 20, 2015 at 4:38 pm

    מה לגבי היבט הטסטביליות?
    (בעיה אמתית שקיימת אצלי בפרויקט), צד-שרת מרנדר templates, עם i18n פנימי בצד שרת ועוד כמה תגים שרק צד-שרת יכול להבין.. איך אפשר להריץ בדיקות על directive עם templateUrl שאפילו אין לי גישה אליו בזמן הריצה של הבדיקה..?
    תודה על ההתייחסות 🙂

     

כתיבת תגובה

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

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת / לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת / לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת / לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת / לשנות )

מתחבר ל-%s

 
%d בלוגרים אהבו את זה: