javascript - Pérdida de alcance al usar ng-include
Tengo este módulo de rutas:
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 de inicio:
<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 addLine $scope.lineText es undefined, esto se puede resolver agregando ng-controller="HomeCtrl" a partial1.html, sin embargo, hace que el controlador se llame dos veces. ¿Qué me estoy perdiendo aquí?
Respuesta #1
Como mencionó @Renan, ng-include crea un nuevo scope hijo. Este scope hereda prototípicamente (ver líneas punteadas a continuación) del scope de HomeCtrl. ng-model="lineText" en realidad crea una propiedad de scope primitiva en el scope hijo, no en el scope de HomeCtrl. Este scope hijo no es accesible para el scope padre/HomeCtrl:
Para almacenar lo que el usuario escribió en el array $scope.lines de HomeCtrl, sugiero que pases el valor a la función addLine:
<form ng-submit="addLine(lineText)">
Además, dado que lineText es propiedad del alcance/parte de ngInclude, siento que debería ser responsable de limpiarlo:
<form ng-submit="addLine(lineText); lineText=''">
La función addLine() se convertiría así:
$scope.addLine = function(lineText) {
$scope.chat.addLine(lineText);
$scope.lines.push({
text: lineText
});
};
Violín.
Alternativas:
- define una propiedad de objeto en el $scope de HomeCtrl, y úsala en la plantilla parcial:
ng-model="someObj.lineText; fiddle - no recomendado, esto es más un truco: usa $parent en el partial para crear/acceder a una propiedad
lineTexten el $scope de HomeCtrl:ng-model="$parent.lineText"; fiddle
Es un poco complicado explicar por qué funcionan las dos alternativas anteriores, pero se explica completamente aquí: ¿Cuáles son las diferencias de matiz de la herencia prototípica/prototípica en AngularJS?
No recomiendo usar this en la función addLine(). Se vuelve mucho menos claro qué alcance se está accediendo/manipulando.
Respuesta #2
Esto se debe a ng-include que crea un nuevo scope hijo, por lo que $scope.lineText no se cambia. Creo que this se refiere al scope actual, por lo que this.lineText debería ser establecido.
Respuesta #3
En lugar de usar this como sugiere la respuesta aceptada, usa $parent en su lugar. Así que en tu partial1.html tendrás:
<form ng-submit="$parent.addLine()">
<input type="text" ng-model="$parent.lineText" size="30" placeholder="Type your message here">
</form>
Si quieres aprender más sobre el scope en ng-include u otras directivas, consulta esto: https://github.com/angular/angular.js/wiki/Understanding-Scopes#ng-include
