RSS

AngularJS Tip 3 – JavaScript Properties in AngularJS

16 נוב


אחת השאלות השכיחות ששואלים אותי, מה הדרך לחבר את
bl שלנו ל- Controller כך שיהיה לנו קל לחבר אותו ב- Binding ב- HTML (ng-model) ?

אפשרות 1:

function UserCtrl(userBL){
    this._bl = userBL;
    this.name    = userBL.name;
    this.address = userBL.address; // address is an object.

}

 

<div ng-controller="UserCtrl as vm">
    <input type="text" ng-model="vm.name" placeholder="name"><br>
    <input type="text" ng-model="vm.address.street" placeholder="street"><br>
    <input type="text" ng-model="vm.address.house" placeholder="house"><br>   
    <br>
    name : {{vm._bl.name}}<br>
    Address : {{vm._bl.address | json }}<br>
</div>

 

 

שפת ה-JavaScript תעתיק את name כ- Copy By Value, ולכן כאשר תעדכנו את הערך ע"י תג input לא יהיה קישור ל- userBL.name.  ב- address (אוביקט) ה-JS מעתיקה את ה-reference כ- Copy By Value ולכן הקישור נשמר.

שימו לב, אם בזמן ריצה יבצעו:

userBL.address = {strees:’abc’, house: 1};
 
נקבל ניתוק מה- this.address, הוא יצביע על האוביקט הישן.
 
אפשרות 2:
 
function UserCtrl(userBL){
    this._bl = userBL;
    Object.defineProperties(this,{
       name : {
           get : function(){
               return userBL.name;
           },
           set : function(value){
               userBL.name = value;
           }
       },
       address : {
           get : function(){
               return userBL.address;
           },
           set : function(value){
               userBL.address = value;
           }
       }
    });
}
 
באפשרות זו יצרתי properties ולכן ה- set’sעובדים על ה-userBL ישירות וכך לא נאבד את ה- binding.
אפשר להמשיך את הגישה הזו גם לקשר שבין ה- BLוה-DAL.
 
(function (angular) {
    ‘use strict’;
    //////////////// AngularJS //////////////
    var mi = angular.module(‘myApp’, [])
    .factory(‘userBL’,blFactory)
    .factory(‘userDTO’,dtoFactory)
    .controller(‘UserCtrl’,UserCtrl);
    //////////////// JavaScript //////////////
    function dtoFactory($log){
        return {
            name: ‘bl-name’,
            address: {
                street: ‘abc’,
                house: 47
            }
        };
    }
    function blFactory($log,userDTO){
        var blUser = Object.defineProperties({},{
            name : {
                get: function(){
                    return userDTO.name;
                },
                set : function(value){
                    userDTO.name = value;
                }
            },
            address : {
                get: function(){
                    return userDTO.address;
                },
                set : function(value){
                    userDTO.address = value;
                }
            }
        });      
        return blUser;
    }

    function UserCtrl(userBL){
        this._bl = userBL;
        Object.defineProperties(this,{
           name : {
               get : function(){
                   return userBL.name;
               },
               set : function(value){
                   userBL.name = value;
               }
           },
           address : {
               get : function(){
                   return userBL.address;
               },
               set : function(value){
                   userBL.address = value;
               }
           }
        });
    }   
})(angular);
 
 

הכתיבה של property קצת ארוכה מבחינת syntax אז כתבתי מתודה עזר:

function createProperty(source,wrapper,property){
    Object.defineProperty(wrapper,property,{
        get: function(){
            return source[property];
        },
        set : function(value){
            source[property] = value;
        }
    });
}
 
ועכשיו ה-controller יכתב כך:
function UserCtrl(userBL){
    this._bl = userBL;
    createProperty(userBL,this,’name’);
    createProperty(userBL,this,’address’);
}
 

שימו לב שבניתי את ה- properties על ה- this, אפשר לבנות אותו ישירות על ה- $scope, לא רעיון טוב. אני הייתי בונה אותו על ה- prototype כדי לא לשכפל פונקציות, של ה- get וה- set לכל מופע של ה- Controller.

function UserCtrl (userBL){
    this._bl = userBL;
    createProperty(userBL,UserCtrl.prototype,'name');
    createProperty(userBL,UserCtrl.prototype,'address');
}

 

הערה אחרונה: ngModelOptions

יש אפשרות באנגולר 1.3 להשתמש ב- ng-model-options="{ getterSetter: true }"זה תחליף ל-properties ע"י הטכנולוגיה של אנגולר, אך אני מאמין שכתיבה של property אמיתי יותר נכונה ויכולה לעבוד בכל השכבות. ראו דוגמא.

 

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

חומר זה הוא חלק מהקורס AngularJS  שאני מעביר בחברות.

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

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

 

3 תגובות ל-“AngularJS Tip 3 – JavaScript Properties in AngularJS

  1. Ori Calvo

    נובמבר 16, 2014 at 11:46 am

    למה לא לכתוב "vm._bl.name" ישירות ב-HTML ?
    רק שבמקום _bl הייתי קורא לזה user

     
    • eyal.vardi

      נובמבר 16, 2014 at 12:19 pm

      הי אורי,
      אפשר לכתוב כך, אך מהר מאוד זה מתחיל להיות מאוד ארוך.

      סיבה נוספת ה-CTRL הוא כמו view על המידע המקורי, כלומר הרבה פעמיים אתה רוצה לשנות את שם של ה-property כמו למשל מ-name ל- fullname.

      ה-property ב-JS מאפשר לך גם להוסיף עיבוד כמו חיבור fName ו- lName ל-property אחד בשם fullName.

       
  2. פרץ

    פברואר 4, 2015 at 11:01 am

    מדוע להוסיף את המאפיינים של הDTO גם לקונטרולר ?

     

להשאיר תגובה

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

הלוגו של WordPress.com

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

תמונת Twitter

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

תמונת Facebook

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

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

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

מתחבר ל-%s

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