170

tengo este módulo dirige:Perder alcance cuando se utiliza ng-incluir

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

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

En la función de $scope.lineTextaddLine es undefined, esto puede ser resuelto mediante la adición de ng-controller="HomeCtrl"-partial1.html, sin embargo, hace que el controlador se llamará dos veces. ¿Que me estoy perdiendo aqui?

Respuesta

76

Esto se debe a ng-include que crea un nuevo ámbito de hijo, por lo que $scope.lineText no se cambia. Creo que this se refiere al alcance actual, por lo que debe establecerse this.lineText.

247

Como se menciona en @Renan, ng-include crea un nuevo ámbito de elemento secundario. Este ámbito hereda de manera prototípica (ver líneas discontinuas a continuación) desde el alcance de HomeCtrl. ng-model="lineText" realmente crea una propiedad de ámbito primitivo en el ámbito secundario, no en el ámbito de HomeCtrl. Este ámbito secundario no es accesible al alcance de los padres/HomeCtrl:

ng-include scope

Para guardar lo que el usuario escribió en una matriz de HomeCtrl $ scope.lines, sugiero que pase el valor de la función AddLine:

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

Además, desde lineText es administrada por el alcance ngInclude/parcial, creo que debe ser responsable de la limpieza que:

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

AddLine Función() se convertiría así:

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

Fiddle.

Alternativas:

  • definir una propiedad de objeto en $ ámbito de HomeCtrl, y el uso que en el parcial: ng-model="someObj.lineText; fiddle
  • no recomendado, esto es más de un truco: use $ parent en el parcial para crear/acceder a una propiedad lineText en el alcance de HomeCtrl $: ng-model="$parent.lineText"; fiddle

que es un poco implicados para explicar por qué las dos alternativas anteriores funcionan, pero se explica completamente aquí: What are the nuances of scope prototypal/prototypical inheritance in AngularJS?

No recomiendo el uso de this en la función() AddLine. Se vuelve mucho menos claro a qué alcance se accede/manipula.

+1

fin entiendo. –

+0

Utilicé ** objetos **, pero el alcance aún estaba enmascarado. Intenté '$ parent' y funcionó muy bien. ¿Por qué lo considera un hack? (Puedo ver que agregaría mantenimiento si refactorizaste tu html) – Jess

+1

La misma pregunta que tuvo @Jess, ¿por qué se considera esto un hack? – qbert65536

3

He descubierto cómo solucionar este problema sin mezclar los datos principales y secundarios. Establezca ng-if en el elemento ng-include y configúrelo en una variable de ámbito. Por ejemplo:

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

En su controlador, cuando se ha activado todos los datos que necesita en su ámbito submarino, a continuación, establezca espectáculo a true. El ng-include copiará en este momento el conjunto de datos en su alcance y lo configurará en su subámbito.

La regla de oro es reducir los datos del alcance más profundo del alcance, de lo contrario tendrá esta situación.

Max

29

En lugar de utilizar this como la respuesta aceptada sugiere, utilice $parent lugar. Así que en su partial1.html tendrá:

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

Si desea obtener más información sobre el alcance de ng-include u otras directivas, mira esto: https://github.com/angular/angular.js/wiki/Understanding-Scopes#ng-include

+1

Para cualquier lector, quiere decir '$ scope. $ Parent' en lugar de' $ parent' no está definido según Angular. – Sebastialonso

+1

¡Esta respuesta me salva el día! Muchas gracias por señalar el uso de $ parent. –

+0

es $ scope. $ Parent pass por referencia? o es solo una copia de los padres? – OMGPOP

Cuestiones relacionadas