2012-11-24 18 views
29

Qual è il modo migliore per passare un valore dal backend a AngularJS nel frontend? Uso Django e i modelli sono in grado di sputare i valori di cui ho bisogno, tuttavia non sono sicuro di quale sia la procedura migliore per trasmettere questi valori ad AngularJS.AngularJS - Passaggio dei valori dal backend al frontend

Pensa a un post di blog e ai suoi commenti, Se avessi un servizio AngularJS che recupera tutti i commenti di un determinato post del blog passando l'ID post al servizio, e Django sta visualizzando il modello HTML e sa cosa è l'ID postale, tuttavia ho bisogno di passare questo post ID a AngularJS e successivamente al servizio.

Un'idea è di averlo nascosto in uno <input> e assegnare questo input a un modello. Non molto attraente.

Un altro è quello di avere una direttiva e superare questo valore in un attributo a questa direttiva, in questo modo sarei in grado di accedere il valore di questo attributo:

// Django (or any backend) is rendering {{ object.value }} 
<div class="myDirective" data-object-id={{ object.value }}> 
    ... 
</div> 

angular.module('myDirectives', []). 
    directive('myDirective', function() { 
     return { 
      restrict: 'C', 
      transclude: false, 
      link: function postLink($scope, $element, $attrs) { 
       // $attrs.objectId would have the value 
      } 
     } 
    }); 

Questi due approcci vanno bene. Ma mi chiedo se c'è un modo più pulito per farlo? Qualche approccio che segue le migliori pratiche di AngularJS?

risposta

22

Se è necessario inizializzare solo una manciata di valori del modello da una vista direttiva ng-init potrebbe essere quello che stai cercando: http://docs.angularjs.org/api/ng.directive:ngInit

Con esso si può semplicemente scrivere:

<div ng-init="myModel=backend-generated-value-here"> 
    ... 
</div> 

Detto quanto sopra, potresti avere un po 'di tempo difficile per trovare le migliori pratiche per il tuo caso d'uso dato che AngularJS è focalizzato su Web 2.0, applicazioni web lato client. Al momento non funziona idealmente con i contenuti generati sul lato server. Potrebbe cambiare nelle versioni future di AngularJS.

+2

Grazie. Direi che circa il 90% della mia applicazione è stata trasformata in client-side mentre il backend (Django) sta servendo esclusivamente API di resto. – abstractpaper

+0

Come dice la documentazione, ng-init è appropriato solo con ng-repeat, un modo migliore sarebbe quello di creare una direttiva personalizzata per passare i dati da html a controller. – Charlesthk

+0

Sono curioso di sapere come sia il compilatore Django che AngularJS dovrebbero funzionare con questa soluzione ... entrambi suppongono di leggere questa stessa area di codice alla volta? – Ricardo

9

Se tutto ciò che serve è impostare i valori iniziali per una determinata "pagina" (che significa chiamata di back-end per una vista), allora puoi fare come hai dimostrato. Vorrei solo renderlo "più pulita" attraverso la creazione di una variabile globale tramite JavaScript, in questo modo:

// Django (or any backend) is rendering {{ object.value }} 
<script> 
    var backendVars = { 
    {{object.name}} : {{object.value}} 
    //and any other objects, manually parsed 
    } 
</script> 

e leggerlo su con angolare sul processo di avvio.

Tuttavia, angularJS è un MVC di sua proprietà, quindi è possibile che si desideri poter impostare/ottenere i dati o i processi dei controller di back-end, senza necessariamente ricaricare l'intera pagina. Il modo "pulito" è quindi di rendere un servizio Web per restituire i dati necessari (ad esempio una vista che restituisce JSON, per esempio) e recuperarlo tramite $ http o servizio $ risorsa:

angular.module('myApp', []). 
    controller('MainCtrl', function($scope, $html) { 
    $html({ 
    method: 'GET', 
    url: '/your/JSON/view.json' 
     }). 
     success(function(data, status){ 
     $scope.yourData = data; 
     }). 
     error(function(data, status){ 
     //whatever you need to do if the data is not available 
     }); 
    } 

Inoltre, ho si dovrebbe notare che non si dovrebbero mettere i dati e la logica direttamente sulle direttive - sono intese per la manipolazione del DOM - invece di ottenere le informazioni su un controller e quindi passarle a una direttiva tramite ereditarietà dell'ambito, attributi o associazione dati bidirezionale. Spero che sia d'aiuto.

+0

Non riesco a richiamare un servizio Web perché dipende dal valore che il backend sta passando. Pensa a un post del blog e alla vista che mostra questo post del blog, se ho un'API che restituisce le informazioni di questo post sul blog, devo passare l'ID del post al servizio web per recuperarne i dati. – abstractpaper

+1

Quindi la prima parte della risposta è ciò che stavi chiedendo. Ma non è "angulary" - si sta utilizzando un framework MVC grande (e fortemente strutturato) per eseguire il lavoro di un framework più piccolo, simile a un toolbelt (come jQuery o qualcosa di più orientato al modello). In angolare, ci si potrebbe pensare in questo modo: perché chiamare you.com/blog/123 e avviare un'app con ogni pagina diversa, quando è possibile chiamare you /#/blog/123 e utilizzare $ route e $ html per ottenere il contenuto del blog, non lasciare mai la pagina (app) mentre modifichi le visualizzazioni? Ancora una volta, se è per qualcosa come un blog, angolare potrebbe non essere la scelta migliore. –

+0

Hai un punto. Preferirei non inquinare il namespace globale però, sto cercando di evitare il più possibile le variabili globali. Grazie per la tua risposta, o andrò per i due approcci che ho citato o usare 'ng-init' come descritto in @ pkozlowski.opensource. – abstractpaper

9

Credo che il modo corretto per fare ciò sia che il server esegua il rendering di uno script con un value provider, quindi lo inserisce in dipendenza dall'app. In questo modo:

index.php:

<html ng-app='myApp'> 

<head> 
    <title>AngularJS Back to Front</title> 
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.min.js"></script> 
    <script src='index.js'></script> 
    <?php 
     $globals = array(
      'count' => 1, 
      'title' => 'Active users', 
      'users' => array(
       'name' => 'john', 
       'age' => 21 
      ) 
     ); 

     $globalsJSON = json_encode($globals) 
    ?> 

    <script> 
     myApp.value('globals', <?=$globalsJSON;?>); 
    </script> 
</head> 

<body ng-controller="myController"> 
    <div>{{title}}</div> 
</body> 

</html> 

indice.js:

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

myApp.controller('myController', [ 'globals', '$scope', function(globals, $scope) { 
    // Copy globals to scope 
    for (var property in globals) { 
     $scope[ property ] = globals[ property ]; 
    } 
}]); 
+0

L'aggiunta di php a una situtation già complicata non mi sembra buona. –

Problemi correlati