2015-07-03 25 views
40

Ho due direttive personalizzate nella mia app angularJS. Un atto come genitore e altro come figlio. Sto provando ad accedere all'ambito del genitore all'interno della direttiva figlio. Ma non sto ottenendo l'output desiderato.Direttiva figlio personalizzata che accede all'ambito del genitore

<div ng-controller="CountryCtrl"> 
{{myName}} 
    <div ng-controller="StateCtrl"> 
     <state nameofthestate="'Tamilnadu'"> 
      <city nameofthecity="'Chennai'"></city> 
     </state> 
    </div> 
</div> 

e il mio script sembra

var app = angular.module("sampleApp",[]); 
app.controller("CountryCtrl",function($scope){ 
    $scope.myName = "India"; 
}); 
app.controller("StateCtrl",function($scope){ 
}); 
app.directive("state",function(){return { 
    restrict : 'E', 
    transclude: true, 
    scope : { myName : '=nameofthestate'}, 
    template:"** {{myName}} is inside {{$parent.myName}}<br/><ng-transclude></ng-transclude>" 
}}); 
app.directive("city",function(){return { 
    restrict : 'E', 
    require:'^state', 
    scope : { myName : '=nameofthecity'}, 
    template:"**** {{myName}} is inside {{$parent.myName}} which is in {{$parent.$parent.myName }}<br/> " 
}}); 

corrispondente JSFiddle disponibile in https://jsbin.com/nozuri/edit?html,js,output

L'uscita che sto ottenendo è

India 
** Tamilnadu is inside India 
**** Chennai is inside India which is in Tamilnadu 

e il risultato atteso è

India 
** Tamilnadu is inside India 
**** Chennai is inside Tamilnadu which is in India 

Qualcuno può educarmi su cosa sto facendo male qui?

+0

scusa, ma il tuo violino non funziona per me. –

+1

ciao http://stackoverflow.com/questions/23437113/get-property-value-from-parent-directive-within-child-directive questo potrebbe aiutarti ad assomigliare a quello che vuoi fare –

+1

Puoi effettuare una trascrizione personalizzata con 'transclude: 'element''. Il costruttore è disponibile in 'link: function (scope, element, attrs, Ctlr, transclude) {}' – gr3g

risposta

28

La direttiva di città $ genitore è un ambito di applicazione di stato transcluso.

L'ambito transuso della direttiva di stato è ereditario per $ genitore della direttiva di stato che è controller, ecco perché $ parent.MyName = India.

Il $ genitore del campo di applicazione della direttiva transclusa è isolato ambito statale (portata = {}), che è il motivo per $ genitore. $ Parent.MyName = Tamilnadu (Parte angolare 1,3 aggiornamento)

enter image description here

un po 'di dettaglio di quello che succede: How to access parent scope from within a custom directive *with own scope* in AngularJS?

transclude: vero - la direttiva crea un nuovo "transclusa" bambino portata, che eredita prototipicamente dal campo di applicazione genitore. Se la direttiva crea anche un ambito isolato, gli ambiti isolati e gli isolati di tipo isolati sono fratelli. La proprietà $ parent di ciascun ambito fa riferimento allo stesso ambito genitore.

Aggiornamento angolare v1.3: se la direttiva crea anche un ambito isolato, l'ambito escluso è ora un figlio dell'ambito isolato. Gli ambiti intercettati e isolati non sono più fratelli. La proprietà $ parent dell'ambito transuso ora fa riferimento all'ambito isolato.

Anche la risposta di Matthew è corretta per le comunicazioni direttive padre-figlio.

15

Funziona per voi? Adattato da this answer.

Non c'è un modo semplice per accedere all'elemento padre del contenuto escluso, quindi inseriamo il controllore genitore nel bambino per accedere al suo ambito.

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

    app.controller("CountryCtrl",function($scope){ 
     $scope.myName = "India"; 
    }); 

    app.controller("StateCtrl",function($scope){ 
    }); 

    app.directive("state",function(){return { 
     restrict : 'E', 
     transclude: true, 
     scope : { myName : '=nameofthestate'}, 
     template:"** {{myName}} is inside {{$parent.myName}}<br/><ng-transclude></ng-transclude>", 
     controller: function ($scope) { 
     this.getName = function() { 
      return $scope.myName; 
     } 
     } 
    }}); 

    app.directive("city",function(){return { 
     restrict : 'E', 
     require:'^state', 
     scope : { myName : '=nameofthecity'}, 
     template:"**** {{myName}} is inside {{parentName}} which is in {{$parent.myName }}<br/> ", 
     link: function(scope, element, attrs, ctrl) { 
     scope.parentName = ctrl.getName(); 
     } 
    }}); 
+1

sì. Funziona. Ma sto accettando la risposta di @ kwan245 in quanto spiega quale errore ho fatto .. :) Grazie Metthew –

+0

Ho usato questo approccio, ma nel mio caso la variabile che contiene il nome è una matrice che può cambiare. C'è un modo per gestire questa situazione in quanto la vista non viene aggiornata per me in questo caso? So che potrei usare gli orologi ma vorrei evitarlo il più possibile. Ho un esempio qui: http://stackoverflow.com/questions/42676713/sharing-data-between-child-directives/42677394 –

3

Quando AngularJS incontra transclude, si clona il HTML prima sostituendolo con il modello o il contenuto TemplateURL.Quindi, quando incontra ng-transclude, compila il contenuto escluso, ma lo lo collega all'ambito padre invece dell'ambito isolato della direttiva . Pertanto, il contenuto escluso ha ancora accesso al controllore genitore e al suo contenuto, mentre l'HTML direttiva ha un ambito isolato (o un nuovo ambito, a seconda dei casi).

AngularJS Up and Running

1

Partenza sollution della mia direttiva, funziona con un sacco di parrents. Quello che ho fatto è stato rimuovere transclude e richiedere params. Non preoccuparti di html sporco, guarda solo js, ​​semplice come f ..: D

CRM.directive('inputwv', function ($compile) { 
    var getTemplate = function(contentType) { 
     var template = ''; 

     switch(contentType) { 
       case '3': 
        template = '<input type="number" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index)" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px;width:100px">' 
        break; 
       case '0': 
        template = '<input type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index)" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">' 
        break; 
       case '1': 
        template = '<input type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index)" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">' 
        break; 
       case '2': 
        template = '<textarea class="materialize-textarea teal-text" type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index)" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">' 
        break; 
       case '4': 
        template = '<input type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index)" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">' 
        break; 
       case '5': 
        template = '<input type="date" class="datepicker" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index)" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px"><script type="text/javascript">$(\'.datepicker\').pickadate({selectMonths: true, selectYears: 15});</script>' 
        break; 
       default: 
        template = '<textarea class="materialize-textarea teal-text" type="text" ng-init="inputHide[$parent.$index][$index]=false" ng-blur="inputHide[$parent.$index][$index]=false" ng-Enterd="updateRecord(row[0], $parent.$index)" ng-Enteru="inputHide[$parent.$index][$index]=false" ng-model="row[$index]" ng-change="row[$index]" ng-value="row[$index]" ng-Right-Click="click(element, $index, $parent.$index)" ng-esc="inputHide[$parent.$index][$index]=false" style="cursor:cell;border-bottom:0px">' 
      } 

     return template; 
} 

    var linker = function(scope, element, attrs) { 
     element.html(getTemplate(attrs.typ)).show(); 

     $compile(element.contents())(scope); 
    } 

    return { 
     restrict: "E", 
     link: linker 
    }; 
}); 
Problemi correlati