170

ich dieses Modul Routen haben:Umfang Verlust bei der Verwendung von ng-umfassen

var mainModule = angular.module('lpConnect', []). 
    config(['$routeProvider', function ($routeProvider) { 
    $routeProvider. 
     when('/home', {template:'views/home.html', controller:HomeCtrl}). 
     when('/admin', {template:'views/admin.html', controller:AdminCtrl}). 
     otherwise({redirectTo:'/connect'}); 
}]); 

HTML Home:

<div ng-include src="views.partial1"></div> 

partial1 HTML:

<form ng-submit="addLine()"> 
    <input type="text" ng-model="lineText" size="30" placeholder="Type your message here"> 
</form> 

HomeCtrl:

function HomeCtrl($scope, $location, $window, $http, Common) { 
    ... 
    $scope.views = { 
     partial1:"views/partial1.html" 
    }; 

    $scope.addLine = function() { 
     $scope.chat.addLine($scope.lineText); 
     $scope.lines.push({text:$scope.lineText}); 
     $scope.lineText = ""; 
    }; 
... 
} 

In der addLine Funktion $scope.lineText ist undefined, kann dies durch Zugabe von ng-controller="HomeCtrl"-partial1.html gelöst werden, aber es bewirkt, dass der Regler zweimal aufgerufen werden. Was fehlt mir hier?

Antwort

76

Dies liegt an ng-include, die einen neuen untergeordneten Bereich erstellt, so dass nicht geändert wird. Ich denke, dass this bezieht sich auf den aktuellen Umfang, so this.lineText sollte eingestellt werden.

247

Wie @Renan erwähnt, erstellt ng-include einen neuen untergeordneten Bereich. Dieser Bereich erbt prototypisch (siehe gestrichelte Linien) vom HomeCtrl-Bereich. ng-model="lineText" erstellt tatsächlich eine primitive Bereichseigenschaft für den untergeordneten Bereich, nicht den Bereich von HomeCtrl. Dieses Kind Umfang nicht zugänglich für die Eltern/HomeCtrl Umfang ist:

ng-include scope

zu speichern, was der Benutzer $ in HomeCtrl der typisierten scope.lines Array, empfehle ich Ihnen den Wert an die AddLine Funktion übergeben:

<form ng-submit="addLine(lineText)"> 

da zusätzlich lineText durch die ngInclude Umfang/Teil gehört, fühle ich sollte es für die Reinigung zuständig:

<form ng-submit="addLine(lineText); lineText=''"> 

Funktion AddLine() würde somit werden:

$scope.addLine = function(lineText) { 
    $scope.chat.addLine(lineText); 
    $scope.lines.push({ 
     text: lineText 
    }); 
}; 

Fiddle.

Alternativen:

  • eine Objekteigenschaft auf HomeCtrl von $ Umfang definieren, und verwendet, die in dem Teil: ng-model="someObj.lineText; fiddle
  • nicht empfohlen, dies ist eher ein Hack: Verwenden Sie $ parent im partiellen Erstellen/Zugriff auf eine lineText -Eigenschaft auf dem HomeCtrl $ -Bereich: ng-model="$parent.lineText"; fiddle

Es ist ein wenig beteiligt, warum die beiden oben genannten Alternativen zu erklären arbeiten, aber es ist voll hier erklärt: What are the nuances of scope prototypal/prototypical inheritance in AngularJS?

ich nicht empfehlen this in AddLine() Funktion. Es wird viel weniger klar, auf welchen Bereich zugegriffen/manipuliert wird.

+1

Endlich verstehe ich. –

+0

Ich habe ** Objekte ** benutzt, aber sie waren noch maskiert. Ich habe versucht, $ Eltern und es hat super funktioniert. Warum halten Sie es für einen Hack? (Ich kann sehen, dass es Wartung hinzufügen würde, wenn Sie Ihren html refaktoriert haben) – Jess

+1

Gleiche Frage @Jess hatte, warum ist das ein hack? – qbert65536

3

Ich habe herausgefunden, wie Sie dieses Problem umgehen können, ohne die Daten des übergeordneten und untergeordneten Bereichs zu mischen. Setzen Sie ng-if auf das Element ng-include und legen Sie es auf eine Bereichsvariable fest. Zum Beispiel:

<div ng-include="{{ template }}" ng-if="show"/> 

In Ihrem Controller, wenn Sie die Daten alles, was Sie in Ihrem Unter Umfang müssen festgelegt haben, dann zeigt auf true gesetzt. Die Datei ng-include kopiert in diesem Moment den Datensatz in Ihrem Bereich und legt ihn in Ihrem Unterbereich fest.

Die Faustregel ist, um Scope-Daten tiefer den Umfang zu reduzieren, sonst haben Sie diese Situation.

Max

29

Statt this der Verwendung als die akzeptierte Antwort vermuten lässt, verwenden $parent statt. Also in Ihrem partial1.html Sie haben:

<form ng-submit="$parent.addLine()"> 
    <input type="text" ng-model="$parent.lineText" size="30" placeholder="Type your message here"> 
</form> 

Wenn Sie mehr über den Umfang in ng-include oder anderen Richtlinien erfahren möchten, check this out: https://github.com/angular/angular.js/wiki/Understanding-Scopes#ng-include

+1

Für jeden Leser bedeutet er '$ scope. $ Parent' statt' $ parent' ist nach Angular undefiniert. – Sebastialonso

+1

Diese Antwort rettet den Tag für mich! Vielen Dank für den Hinweis auf die Verwendung von $ Eltern. –

+0

ist $ scope. $ Parent pass by reference? oder es ist nur eine Kopie von Eltern? – OMGPOP

Verwandte Themen