2013-06-27 21 views
21

Come posso utilizzare il valore di un attributo in una direttiva? Il mio elemento è simile al seguente:Usa gli attributi della direttiva angolare nel suo modello

<div class="tooltip-icon" 
    data-my-tooltip="click" 
    data-tooltip-title="foo" 
    data-tooltip-content="test content"></div> 

Vorrei utilizzare che nel modello della mia direttiva, che assomiglia a questo:

mainApp.directive('myTooltip', 
    function() { 

     // allowed event listeners 
     var allowedListeners = ["click"]; 

     return { 
      restrict: 'A', 
      template: '<div class="tooltip-title">...</div>' + 
         '<div class="tooltip-content">' + 
         '...</div>', 
      link: function(scope, elm, attrs) { 
       if(allowedListeners.indexOf(attrs.myTooltip) != -1){ 
        elm.bind(attrs.myTooltip, function(){ 
         ... 
        }); 
       } 

      } 
     }; 
    } 
); 

Dove i puntini triple sono ci dovrebbe essere il codice, ma io non riesco a capire come ottenere il contenuto dell'oggetto attrs (attrs.tooltipTitle, ecc.) in quel modello.

risposta

32

È possibile estrarre gli attributi fuori e metterli nel campo di applicazione della direttiva in questo modo:

angular.module('myApp', []). 
directive('myTooltip', function ($log) { 
    // allowed event listeners 
    var allowedListeners = ["click"]; 
    return { 
     restrict: 'A', 
     template: '<div class="tooltip-title">{{tooltipTitle}}</div>' + 
        '<div class="tooltip-content">' + 
        '{{tooltipContent}}</div>', 
     scope: { 
      tooltipTitle: '@tooltipTitle', 
      tooltipContent: '@tooltipContent' 
     }, 
     link: function (scope, elm, attrs) { 
      if (allowedListeners.indexOf(attrs.myTooltip) != -1) { 
       elm.bind(attrs.myTooltip, function() { 
        $log.info('clicked'); 
       }); 
      } 

     } 
    }; 
}); 

Ecco violino: http://jsfiddle.net/moderndegree/f3JL3/

+0

Per quanto riguarda lo scope, sono disponibili i contenuti di \ @tooltipTitle e \ @tooltipcontent che estrae il contenuto nell'ambito di questa istanza, ovvero posso avere 2 tooltip nella stessa pagina e non sovrascriveranno il titolo e il contenuto di eachothers? – Maarten

+1

Dovresti essere in grado di averne quante ne vuoi nella pagina. Sta tirando dagli attributi DOM. Puoi scoprire di più su come l'ho fatto qui: http://docs.angularjs.org/guide/directive#directivedefinitionobject –

3

Questa domanda è già stato risposto, ma sono condividerò anche il mio codice angolare, in quanto questa è un'area in cui è spesso utile vedere alcuni esempi di lavoro.

Ho un paio di pagine web, ognuno con il proprio controllore angolare, e volevo un modo per avere uno "Attendere prego" pop-up in ogni pagina, che appare quando una qualsiasi delle pagine chiamato un HTTP GET o POST servizio web.

enter image description here

Per fare questo, ciascuno dei miei pagine web contiene questa linea:

<please-wait message="{{LoadingMessage}}" ></please-wait> 

... che è destinato a un $scope nel controllore di quella pagina ...

$scope.LoadingMessage = "Loading the surveys..."; 

Ecco il codice per la mia direttiva <please-wait>:

myApp.directive('pleaseWait', 
    function ($parse) { 
     return { 
      restrict: 'E', 
      replace: true, 
      scope: { 
       message: '@message' 
      }, 
      link: function (scope, element, attrs) { 
       scope.$on('app-start-loading', function() { 
        element.fadeIn(); 
       }); 
       scope.$on('app-finish-loading', function(){ 
        element.animate({ 
         top: "+=15px", 
         opacity: "0" 
        }, 500); 
       }); 
      }, 
      template: '<div class="cssPleaseWait"><span>{{ message }}</span></div>' 
     } 
    }); 

Si noti come raccoglie l'attributo message ({{LoadingMessage}} in questo esempio) e può visualizzare il suo valore nel modello della direttiva.

(Che in realtà è l'unica parte della mia risposta che risponde direttamente a questa domanda, ma continuate a leggere, per qualche Tips'n'Tricks ...)

Ora, la parte interessante è che ognuno di mia i controller chiamano un servizio dati angolare ogni volta che desidera caricare o salvare dati da/a un servizio Web.

$scope.LoadAllSurveys = function() { 
     DataService.dsLoadAllSurveys($scope).then(function (response) { 
      // Success 
      $scope.listOfSurveys = response.GetAllSurveysResult; 
     }); 
    } 

La funzione dsLoadAllSurveys assomiglia a questo ...

myApp.webServicesURL = "http://localhost:15021/Service1.svc"; 

myApp.factory('DataService', ['$http', 'httpPostFactory', 'httpGetFactory', 
    function ($http, httpPostFactory, httpGetFactory) { 

     var dsLoadAllSurveys = function (scope) 
     { 
      // Load all survey records, from our web server 
      var URL = myApp.webServicesURL + "/getAllSurveys"; 
      return httpGetFactory(scope, URL); 
     } 

     return { 
      dsLoadAllSurveys: dsLoadAllSurveys 
     } 
    }]); 

e, soprattutto, tutti i "GET" le chiamate di servizio web vanno via la seguente funzione, che visualizza il controllo Si prega di aspettare per noi .. quindi lo fa andare via quando il servizio è completato.

myApp.factory('httpGetFactory', function ($http, $q) { 
    return function (scope, URL) { 
     // This Factory method calls a GET web service, and displays a modal error message if something goes wrong. 
     scope.$broadcast('app-start-loading');   // Show the "Please wait" popup 

     return $http({ 
      url: URL, 
      method: "GET", 
      headers: { 'Content-Type': undefined } 
     }).then(function (response) { 
      scope.$broadcast('app-finish-loading');  // Hide the "Please wait" popup 
      if (typeof response.data === 'object') { 
       return response.data; 
      } else { 
       // invalid response 
       return $q.reject(response.data); 
      } 
     }, function (errorResponse) { 
      scope.$broadcast('app-finish-loading');  // Hide the "Please wait" popup 

      // The WCF Web Service returned an error. 
      // Let's display the HTTP Status Code, and any statusText which it returned. 
      var HTTPErrorNumber = (errorResponse.status == 500) ? "" : "HTTP status code: " + errorResponse.status + "\r\n"; 
      var HTTPErrorStatusText = errorResponse.statusText; 

      var message = HTTPErrorNumber + HTTPErrorStatusText; 

      BootstrapDialog.show({ 
       title: 'Error', 
       message: message, 
       buttons: [{ 
        label: 'OK', 
        action: function (dialog) { 
         dialog.close(); 
        }, 
        draggable: true 
       }] 
      }); 

      return $q.reject(errorResponse.data); 
     }); 
    }; 
}); 

Quello che mi piace di questo codice è che questa funzione si occupa di visualizzare/nascondere la "Attendere" pop-up, e se si verifica un errore, sembra anche dopo aver visualizzato il messaggio di errore (utilizzando l'eccellente libreria BootstrapDialog), prima di restituire il risultato dell'errore al chiamante.

Senza questa funzione di fabbrica, ogni volta che uno dei miei controller Angular chiamava un servizio Web, avrebbe bisogno di mostrare, quindi nascondere, il controllo "Attendere" e controllare gli errori.

Ora posso chiamare il mio servizio web e lasciare it per informare l'utente se qualcosa va storto, altrimenti posso presumere che tutto funzioni e elaborare i risultati.

Ciò mi consente di avere un codice molto più semplice. Ricordo come ho chiamato quel servizio web:

DataService.dsLoadAllSurveys($scope).then(function (response) { 
     // Success 
     $scope.listOfSurveys = response.GetAllSurveysResult; 
    }); 

Quel codice sembra come se non sta facendo alcuna gestione degli errori, mentre in realtà, è tutto curato dietro le quinte in un unico luogo.

Sto ancora ottenendo il blocco delle fabbriche e dei servizi dati con Angular, ma penso che questo sia un esempio da scartare di come possono aiutare.

Spero che questo abbia senso e aiuta.

Problemi correlati