Pérdida de alcance al usar ng-include


Tengo este módulo 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 sea llamado dos veces. ¿Qué me estoy perdiendo aquí?

Author: Xufox, 2012-07-10

4 answers

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

 79
Author: Renan Tomal Fernandes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-06 10:18:05

Como @Renan mencionó, ng-include crea un nuevo ámbito secundario. Este ámbito hereda prototípicamente (consulte las líneas discontinuas a continuación) del ámbito HomeCtrl. ng-model="lineText" en realidad crea una propiedad de ámbito primitivo en el ámbito hijo, no en el ámbito de HomeCtrl. Este ámbito hijo no es accesible para el ámbito padre/HomeCtrl:

ng-incluir alcance

Para almacenar lo que el usuario escribió en el scope scope de HomeCtrl.lines array, le sugiero que pase el valor a la función addLine:

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

Además, dado que lineText es propiedad de ngInclude scope / partial, creo que debería ser responsable de limpiarlo:

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

Function addLine() se convertiría así en:

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

Fiddle .

Alternativas:

  • defina una propiedad de objeto en el scope scope de HomeCtrl, y utilícela en el parcial: ng-model="someObj.lineText; fiddle
  • no se recomienda, esto es más un truco: use partial parent en el parcial para crear / acceder a una propiedad lineText en el HomeCtrl scope scope: 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 los matices de la herencia prototípica / prototípica de alcance en AngularJS?

No recomiendo usar this en la función addLine (). Se vuelve mucho menos claro a qué ámbito se accede/se manipula.

 253
Author: Mark Rajcok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:12

En lugar de usar this como sugiere la respuesta aceptada, use $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 desea obtener más información sobre el ámbito en ng-include u otras directivas, consulte esto: https://github.com/angular/angular.js/wiki/Understanding-Scopes#ng-include

 30
Author: ErwinGO,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-05 05:55:10

He descubierto cómo solucionar este problema sin mezclar datos de alcance primario y secundario. Establecer un ng-if en el elemento ng-include y establecerlo en una variable de ámbito. Por ejemplo :

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

En su controlador, cuando haya establecido todos los datos que necesita en su sub ámbito, establezca show en true. El ng-include copiará en este momento el conjunto de datos en su ámbito y lo establecerá en su sub ámbito.

La regla general es reducir los datos del ámbito más profundo que el ámbito, de lo contrario, tiene esto situación.

Max

 3
Author: wascou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-04 13:39:28