170

mam ten moduł tras:Utrata zakresu przy użyciu ng obejmują

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'}); 
}]); 

Home HTML:

<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 = ""; 
    }; 
... 
} 

W addLine funkcji $scope.lineText jest undefined, to może być rozwiązany poprzez dodanie ng-controller="HomeCtrl" do partial1.html, powoduje to jednak kontroler na miano dwukrotnie. Czego tu mi brakuje?

Odpowiedz

76

Dzieje się tak z powodu ng-include, który tworzy nowy zakres podrzędny, więc $scope.lineText nie został zmieniony. Myślę, że this odnosi się do bieżącego zakresu, więc należy ustawić this.lineText.

247

Jak wspomniano w @Renan, ng-include tworzy nowy zakres podrzędny. Ten zakres prototypowo dziedziczy (patrz linie przerywane poniżej) z zakresu HomeCtrl. ng-model="lineText" faktycznie tworzy prymitywną właściwość zakresu na zasięgu podrzędnym, a nie w zasięgu HomeCtrl. Ten zakres dziecko nie jest przystosowany do zakresu rodzic/HomeCtrl:

ng-include scope

Aby zapisać to, co użytkownik wpisze w HomeCtrl za $ scope.lines tablicy, proponuję przekazać wartość do funkcji addLine:

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

Ponadto, ponieważ lineText jest własnością zakresu ngInclude/częściowe, czuję powinno być odpowiedzialne za wyczyszczenie go:

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

Funkcja addLine() byłoby zatem stać:

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

Fiddle.

Alternatywy:

  • określają właściwość obiektu na HomeCtrl za $ zakresu i użyć jej w częściowej: ng-model="someObj.lineText; fiddle
  • nie polecam, to jest bardziej Hack: użyć $ rodziców w częściowym do tworzenia/dostęp do właściwości lineText na HomeCtrl $ zakresie: ng-model="$parent.lineText"; fiddle

To trochę zaangażować się wyjaśnić, dlaczego działają powyższe dwie alternatywy, ale jest w pełni wyjaśnione tutaj: What are the nuances of scope prototypal/prototypical inheritance in AngularJS?

Nie polecam korzystania this w funkcji() addLine. Staje się o wiele mniej jasne, do którego zakresu jest uzyskiwany dostęp/manipulowany.

+1

Wreszcie rozumiem. –

+0

Użyłem ** obiektów **, ale zakres był nadal zamaskowany. Próbowałem "$ parent" i działało świetnie. Dlaczego uważasz to za włamanie? (Widzę, że dodawałby konserwację, jeśli refaktoryzowałeś swój html). – Jess

+1

To samo pytanie @ Nie, dlaczego jest to uważane za włamanie? – qbert65536

3

Zorientowałem się, jak obejść ten problem bez mieszania danych nadrzędnych i podrzędnych. Ustaw element ng-if na elemencie ng-include i ustaw go na zmienną zakresu. Na przykład:

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

W kontrolerze, gdy zostało ustawione wszystkie potrzebne dane w sub zakresu, a następnie ustawić show true. ng-include skopiuje w tym momencie zestaw danych w twoim zasięgu i ustawi go w twoim sub-oscyloskopie.

Reguła polega na zmniejszeniu zakresu danych w szerszym zakresie, w przeciwnym razie wystąpi taka sytuacja.

Max

29

Zamiast this jak sugeruje przyjęty odpowiedź, zamiast używać $parent. Tak więc w swojej partial1.html musisz:

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

Jeśli chcesz dowiedzieć się więcej o zakresie w ng-include lub innych dyrektyw, to sprawdzić: https://github.com/angular/angular.js/wiki/Understanding-Scopes#ng-include

+1

Dla każdego czytnika, oznacza on '$ scope. $ Parent' zamiast' $ parent' jest niezdefiniowany zgodnie z Angular. – Sebastialonso

+1

Ta odpowiedź ratuje mi dzień! Bardzo dziękuję za wskazanie korzystania z $ parent. –

+0

is $ scope. $ Parent pass przez referencję? czy to tylko kopia rodzica? – OMGPOP

Powiązane problemy