נגישות       נגישות
שינוי גודל טקסט:
א א א
שינוי צבעי האתר:
? מקשי קיצור:

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

הפעלת מקשי הקיצור תלויה בדפדפן שבו אתם משתמשים.

Internet Explorer, Chrome ובגרסאות ישנות של Firefox: לחצו על מקש Alt ועל מקש המספר או האות על-פי הרשימה. ב Firefox 3 ומעלה: לחצו על המקשים Alt + Shift + המספר או האות.

S - עבור לתוכן הדף
L - חיפוש
1- עמוד הבית
2 - פרוייקטים
3 - מדריכים
4 - אודות
5 - צרו קשר
6 - הצהרת נגישות
 

מדריך אנגולר: custom directives וסרטים

מחבר:
בתאריך:

 

 

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


<div movie-result></div>
<div movie-result></div>
<div movie-result></div>

 

נתחיל לפתח את האפליקציה...

האפליקציה כוללת את 5 המרכיבים הבאים:

  1. תבנית ה-HTML העיקרית שבה נגדיר את האלמנט שאנחנו מעוניינים להחליף.
  2. קוד ה-angular הבסיסי שכולל את הקונטרולר.
  3. קוד ה-custom directive
  4. הטמפלייט שמחליף את האלמנט
  5. אפשרות לטמפלייט לגשת למידע בקונטרולר

 

1. תבנית ה-HTML העיקרית

נתחיל מיצירת תבנית ה-HTML הבסיסית, שכוללת:

  • הגדרת ng-app על כל דף ה-HTML.
  • הגדרת ng-controller על div מסוים שבתוכו יתבצע תהליך החלפת האלמנטים בתוכן של custom directive.
  • בתוך הקונטרולר, נגדיר אלמנט עם attribute מיוחד movie-result, שיוחלף בהמשך בתוכן מלא ששייך לסרט.
<div movie-result></div>


<html lang="en" ng-app="myApp">
<head>
    <title>Custom directives</title>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
</head>
<body dir="ltr">
    <div ng-controller="mainCtrl">
        <h3>Movies</h3>
        <div movie-result></div>
    </div>
</div>
</body>
</html>

הגדרנו על האלמנט שאנחנו מעוניינים להחליף את השדה movie-result. שם שמתאר האלמנט, ומציית לכללים שאנגולר מכתיב לנו הכוללים שם שמכיל אותיות קטנות בלבד, ומילים שמופרדות בקו מפריד.

* זכרו את שם השדה movie-result כי נתייחס אליו בהמשך כשניתן שם ל-directive.

 

2. קוד ה-angular הבסיסי שכולל את הקונטרולר

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

  • הגדרת האפליקציה ששמה myApp.
  • הגדרת הקונטרולר ששייך לאפליקציה.
  • בתוך הקונטרולר נגדיר אובייקט movie ששייך ל-scope, וכולל את שם הסרט והשנה בה נוצר.


var myApp = angular.module("myApp",[]);

myApp.controller("mainCtrl",function($scope){
    $scope.movie = {
        name: 'Captain America',
        year: '2016'
    }
});

 

3. קוד ה-custom directive

נוסיף לקוד האנגולר גם קוד של directive, שיקבל את השם movieResult. שם זה נגזר מה-custom attribute שהגדרתי על האלמנט שאני רוצה להחליף: movie-result. כדי ליצור את שם ה-directive מוחקים את כל הקווים המפרידים, ומתחילים כל מילה מלבד המילה הראשונה באות גדולה (lower camel case).

קוד ה-directive מחזיר אובייקט שכולל את השדות הבאים:

  • templateUrl, שמגדיר את המקום שבו נמצא ההטמ"ל שיהווה את הטמפלייט של ה-custom directive.
  • scope שמגדיר את מקור המידע שיהיה נגיש לטמפלייט (ועל זה עוד נרחיב בהמשך).


myApp.directive("movieResult",function(){
    return {
        templateUrl: 'directives/movieresult.html',
        scope: {
            
        }
    }
});

 

4. הטמפלייט שמחליף את האלמנט

הטמפלייט שמחליף את האלמנט נמצא בקובץ 'directives/movieresult.html'. הטמפלייט כולל את השדות שאנחנו מעוניינים שיוחלפו בתוכן אמיתי.


<div>
	<h4>{{ movieName }}</h4>
	<p>{{ movieYear }}</p>	
</div>
<hr />

אם נריץ את מה שכתבנו עד כה, לא נראה כלום מפני שאין לטמפלייט גישה למידע באובייקט שנמצא ב-scope הקונטרולר בעוד ל-directive יש scope משלה.

 

5. נאפשר לטמפלייט לקבל מידע מהאובייקט שנמצא בתוך הקונטרולר

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

בטמפלייט הראשי (index.html), נגדיר את המידע שאנחנו רוצים להעביר באמצעות custom attribute, שכולל את השם שאנחנו רוצים לתת למידע שאנו רוצים להעביר (לדוגמה, movie-name), וגם את המידע הקונקרטי שאנו מעוניינים שיעבור (לדוגמה, "{{ movie.name }}").


<div ng-controller="mainCtrl">
    <h3>Movies</h3>
    <div movie-result 
             movie-name="{{ movie.name }}" 
             movie-year="{{ movie.year }}"></div>
</div>

המידע הקונקרטי שאנו מעוניינים להעביר מוגדר בין זוג שפמים ({{}}) מפני שמדובר במחרוזת.

נגדיר ב-scope של ה-directive שה-custom attribute שהגדרנו מקבל ערך של טקסט מהקונטרולר באמצעות הסמל @. (למה? ככה!)

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


myApp.directive("movieResult", function(){
  return {
    templateUrl: 'directives/movieresult.html',
    scope : {
      movieName: "@",
      movieYear: "@"
    }
  }
});

 

הקוד המלא

index.html


<html lang="en" ng-app="myApp">
<head>
    <title>Custom directives</title>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
</head>
<body dir="ltr">
    <div ng-controller="mainCtrl">
        <h3>Movies</h3>
        <div movie-result 
             movie-name="{{ movie.name }}" 
             movie-year="{{ movie.year }}">
        </div>
    </div>
</div>
<script>
var myApp = angular.module("myApp",[]);

myApp.controller("mainCtrl",function($scope){
    $scope.movie = {
        name: 'Captain America',
        year: '2016'
    }
});

myApp.directive("movieResult", function(){
  return {
    templateUrl: 'directives/movieresult.html',
    scope : {
      movieName: "@",
      movieYear: "@"
    }
  }
});
</script>
</body>
</html>

 

directives/movieresult.html


<div>
	<h4>{{ movieName }}</h4>
	<p>{{ movieYear }}</p>	
</div>
<hr />

 

 

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

 

כיצד להעביר אובייקט?

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

1. נגדיר את האובייקט שרוצים להעביר בטמפלייט הראשי. movie-object="movie"


<div ng-controller="mainCtrl">
    <h3>Movies</h3>
    <div movie-result movie-object="movie"></div>
</div>

 

2. נגדיר ב-scope של ה-directive שה-custom attribute שהגדרנו מקבל אובייקט מהקונטרולר.

המשמעות של "=" היא קשירה דו-כיוונית של האובייקט.


myApp.directive("movieResult", function(){
    return {
        templateUrl: 'directives/movieresult.html',
        scope : {
            movieObject: "="
        }
    }
});

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

 

3. נשנה את הדירייקטיב, כך שידע להציג את המידע שמתקבל מהאובייקט.


<div>
	<h4>{{ movieObject.name }}</h4>
	<p>{{ movieObject.year }}</p>
</div>
<hr />

 

כיצד להעביר את הסוג הבוליאני?

שימו לב שאת הסוג בוליאני (true/false) מעבירים כמו אובייקט.

 

כיצד להעביר פונקציה?

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

1. נוסיף את הפונקציה לקונטרולר.


myApp.controller("mainCtrl", function($scope){
    $scope.movie = {
            name: 'Captain America',
            year: '2016'
    }
    
    $scope.formatMovieTitle = function(movie){
        return movie.name + ', ' + movie.year;
    }
});

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


< div movie-result 
         movie-object="movie" 
         format-movie-title-function="formatMovieTitle(movie)"> </div>

3. נגדיר בקוד ה-directive שאחנו מעבירים פונקציה באמצעות &.


myApp.directive("movieResult", function(){
    return {
        templateUrl: 'directives/movieresult.html',
        scope : {
            movieObject: "=",
            formatMovieTitleFunction: "&"
        }
    }
});

4. בטמפלייט של ה-directive, נשלב את המחרוזת שמחזירה הפונקציה. נעביר לפונקציה מפת אובייקטים שממפה על הפרמטר שאנו מצפים לו בפונקציה (movie) את האובייקט שכבר קיים בטמפלייט (movieObject).


< div>
  <h4>{{ movieObject.name }}< /h4>
  <p>{{ formatMovieTitleFunction({movie: movieObject}) }}</p>
< /div>
< hr />

 

כיצד להציג מספר תוצאות במקום רק אחת?

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

1. נגדיר בקונטרולר, מערך של אובייקטים ששמו movies, והוא כולל מידע על מספר סרטים.


myApp.controller("mainCtrl", function($scope){
    $scope.movies = [
        {
            name: 'Captain America',
            year: '2016'
        },
        {
            name: 'Mad Max',
            year: '2015'
        },
        {
            name: 'Godzilla',
            year: '2014'
        }
    ]
    
    $scope.formatMovieTitle = function(movie){
        return movie.name + ', ' + movie.year;
    }
});

2. בטמפלייט הראשי נשתמש בng-repeat כדי להציג את האלמנט כמה פעמים שצריך.


< div ng-repeat="movie in movies">
    < div movie-result 
		 movie-object="movie" 
		 format-movie-title-function="formatMovieTitle(movie)"> < /div>
< /div>

 

כיצד לשנות את הטמפלייט של הדיירקטיב לאחר הקשירה?

שום מדריך על custom directives באנגולר אינו יכול להיות שלם בלי ללמד על link כי הפונקציה link רצה על כל האלמנטים שבתוך ה-custom directive. שינויים הכוללים העברת מידע באמצעות משתנים והרצת פונקציות.

את הפונקציה link מעבירים כאופציה לקוד ה-directive, ובתוך ה-link ניתן לבצע פעולות שונות.

בדוגמה זו, נריץ בתוך הפונקציה link קוד שמוסיף קלאס לאלמנט רק במידה ושם הסרט הוא Mad Max.


myApp.directive("movieResult", function(){
    return {
        templateUrl: 'directives/movieresult.html',
        scope : {
            movieObject: "=",
            formatMovieTitleFunction: "&"
        },
        link: function(scope, elements, attrs){
            
            if(scope.movieObject.name == 'Mad Max'){
                elements.addClass("red");
            }
        }
    }
});

 

מה זה transclusion וכיצד להשתמש בזה?

transclusion זו חתיכת מילה, אבל המשמעות היא פשוטה למדי, והיא שניתן לכלול טמפלייט אחד בתוך טמפלייט אחר.

בדוגמה הבאה, נוסיף לתצוגה אלמנט נוסף באמצעות transclusion.

נתחיל מזה שנוסיף טקסט ישירות לתוך הטמפלייט הראשי שנמצא ב-index.php. למרות שהוספנו את הטקסט לטמפלייט לא נראה אותו מפני שכל האלמנט מוחלף ב-custom directive על ידי אנגולר.


<div ng-repeat="movie in movies">
	<div movie-result 
		 movie-object="movie" 
		 format-movie-title-function="formatMovieTitle(movie)">

	* Not comprehensive.

	</div>
</div>

כדי שנוכל לצפות באלמנט שהוספנו, עלינו לבצע את שתי הפעולות הבאות:

1. ב-directive נגדיר transclude: true


myApp.directive("movieResult",function(){
    return {
        templateUrl: 'directives/movieresult.html',
        scope : {
            movieObject: "=",
            formatMovieTitleFunction: "&"
        },
        link: function(scope,elements,attrs){
            
            if(scope.movieObject.name == 'Mad Max'){
                elements.addClass("red");
            }
        },
        transclude: true
    }
});

2. בטמפלייט של ה-directive ניצור אלמנט שיכיל את ה-transclusion.


<div>
	<h4>{{ movieObject.name }}</h4>
	<p>{{ formatMovieTitleFunction({movie: movieObject}) }}</p>
	<p><ng-transclude></ng-transclude></p>
</div>
<hr />

מדריכי AngularJS

הוסף תגובה חדשה

 

= 6 + 3