181 votes

AngularJS - perte de portée lors de l'utilisation de ng-include

J'ai ce module routes:

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

dans la fonction addLine, $ scope.lineText n'est pas défini, cela peut être résolu en ajoutant ng-controller = "HomeCtrl" à partial1.html, mais cela provoque l'appel du contrôleur deux fois, qu'est-ce que je manque ici?

260voto

Mark Rajcok Points 85912

@Renan mentionné, ng-inclure crée un nouvel enfant. Ce champ fait hérite (voir les lignes en pointillés ci-dessous) à partir de la HomeCtrl portée. ng-model="lineText" crée en fait une primitive de la portée de propriété sur l'enfant, pas HomeCtrl du champ d'application. Cet enfant n'est pas accessible pour le parent/HomeCtrl portée:

ng-include scope

Pour stocker ce que l'utilisateur a tapé dans HomeCtrl de dollars de portée.les lignes de tableau, je vous suggère de passer la valeur de la addLine fonction:

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

En outre, depuis lineText est la propriété de la ngInclude portée/partiel, je pense qu'il devrait être chargé de la compensation:

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

Fonction addLine() deviendrait ainsi:

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

Le violon.

Alternatives:

  • définir une propriété de l'objet sur HomeCtrl de dollars de portée, et de l'utiliser dans le partiel: ng-model="someObj.lineText; violon
  • n'est pas recommandé, c'est plus un hack: utiliser $parent dans le partiel pour créer ou accéder à un lineText bien sur la HomeCtrl $portée: ng-model="$parent.lineText"; violon

C'est un peu à expliquer pourquoi les deux alternatives de travail, mais il est entièrement expliquée ici: Quelles sont les nuances de portée prototypes / l'héritage par prototype dans AngularJS?

Je ne recommandons pas d'utiliser des this dans le addLine() fonction. Il devient beaucoup moins clair dont la portée est en cours d'accès/manipulé.

83voto

Renan Tomal Fernandes Points 5540

Ceci est dû au fait que ng-include crée une nouvelle étendue enfant, de sorte que $ scope.lineText n'est pas modifié. Je pense que this réfèrent à la portée actuelle, donc this.lineText devrait être défini.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X