Ng-include kullanırken kapsamı kaybetme


181

Bu modül yolları var:

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

Ev HTML'si:

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

In addLinefonksiyonu $scope.lineTextolduğunu undefined, bu ekleyerek çözülebilir ng-controller="HomeCtrl"için partial1.htmlancak kontrolör iki kez çağrılacak neden olur. Burada ne eksik?

Yanıtlar:


83

Bunun nedeni, ng-includeyeni bir çocuk kapsamı oluşturmasıdır, bu nedenle $scope.lineTextdeğişmez. Bunun thismevcut kapsamı ifade ettiğini düşünüyorum , bu yüzden this.lineTextayarlanmalıdır.


260

@Renan'ın belirttiği gibi, ng-include yeni bir alt kapsam oluşturur. Bu kapsam, HomeCtrl kapsamından prototip olarak miras alır (aşağıdaki kesikli çizgilere bakın). ng-model="lineText"aslında HomeCtrl'in kapsamı değil, alt kapsamda ilkel bir kapsam özelliği oluşturur. Bu alt kapsama üst / HomeCtrl kapsamı tarafından erişilemez:

ng-include kapsamı

Kullanıcının HomeCtrl'in $ scope.lines dizisine yazdıklarını saklamak için, değeri addLine işlevine geçirmenizi öneririm:

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

Buna ek olarak, lineText ngInclude kapsamına / kısmi sahip olduğu için, temizlemekten sorumlu olması gerektiğini hissediyorum:

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

AddLine () işlevi şu şekilde olur:

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

Keman .

Alternatifler:

  • HomeCtrl'in $ kapsamında bir nesne özelliği tanımlayın ve bunu kısmi olarak kullanın ng-model="someObj.lineText:; Vaktini boşa harcamak
  • önerilmez, bu bir hack daha: lineTextHomeCtrl $ kapsamında bir özellik   oluşturmak / erişmek için kısmi olarak $ parent kullanın ng-model="$parent.lineText":; Vaktini boşa harcamak

Yukarıdaki iki alternatifin neden işe yaradığını açıklamak biraz dahil olmakla birlikte, burada tam olarak açıklanmaktadır: AngularJS'de prototip / prototip kalıtım kapsamının nüansları nelerdir?

thisAddLine () işlevinde kullanmanızı önermiyorum. Hangi kapsama erişildiği / manipüle edildiği çok daha az netleşir.


1
Sonunda anlıyorum.
Scott Tesler

1
@Jess'in sahip olduğu aynı soru, bu neden bir hack olarak kabul ediliyor?
qbert65536

13
@ qbert65536, aslında bir hack / kırılgandır çünkü HTML'nizi yeniden yapılandırırsanız, artık çalışmayabilir. Örneğin, $parent.$parent...çalışmasını sağlamak için kullanmanız gerekebilir . Başka bir deyişle, kullanarak $parentDOM yapısı hakkında varsayımlar yapar.
Mark Rajcok

6
@Jess 'bağlantısı yukarıdaki Anlama Kapsamları ngInclude olarak değiştirildi . Tüm sayfayı okuyun, harika.
mraaroncruz

1
Bu çok ayrıntılı bir cevap ama hepsini başarılı olmadan denedim. Bir denetleyiciye bazı girdi içeren bir form var ve denetleyicinin sonucu başka bir div üzerinde görüntülenmelidir. Herhangi bir girdi girdikten sonra senkronizasyon kaybedilecek ve uygulama çalışırken view div üzerinde sabit bir 0.00 değerine sahip olacağım.
zahra

33

Bunun yerine kullanmanın thiskabul cevap anlaşılacağı gibi, kullanmak $parentyerine. Yani partial1.htmlsizde:

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

Kapsam ng-includeveya diğer yönergeler hakkında daha fazla bilgi edinmek istiyorsanız, şuraya bakın : https://github.com/angular/angular.js/wiki/Understanding-Scopes#ng-include


1
Herhangi bir okuyucu, o anlamına $scope.$parentyerine $parentaçısal göre tanımlanmamış.
Sebastialonso

1
Bu cevap günü benim için kurtarıyor! $ Parent kullanımını işaretlediğiniz için çok teşekkür ederiz.
Derek Webb

kapsam. $ referans ile üst geçiş mi? ya da sadece ebeveynin bir kopyası mı?
OMGPOP

1
@Sebastiallonso yanlış. $ scope. $ parent.lineText tanımsız. $ parent.lineText çalışıyor, this.lineText veya sadece lineText de çalışıyor
OMGPOP

Bu $scope.$parentbenim için açısal 1.3.20 benim için çalışıyor
radtek

4

Üst ve alt kapsam verilerini karıştırmadan bu soruna geçici bir çözüm bulmak için düşündüm. Bir Set ng-ifüzerinde ng-includeeleman ve bir kapsam değişken olarak ayarlayın. Örneğin :

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

Denetleyicinizde, alt kapsamınızda ihtiyacınız olan tüm verileri ayarladıktan sonra şovu olarak ayarlayın true. ng-includeSenin kapsamında şu anda veri kümesini kopyalayıp alt kapsamı içinde ayarlayacaktır.

Temel kural, kapsam verilerini kapsamın derinliklerine indirmektir, aksi takdirde bu duruma sahipsiniz.

maksimum


Benzer bir sorun için bu yaklaşımı kullanıyorum ama tüm durumlar için uygun değil. Özellikle içerilen elemanın asla gizlenmemesini istediğinizde ...
iSpithash
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.