Kehilangan ruang lingkup saat menggunakan ng-include

181

Saya memiliki rute modul ini:

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

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

Dalam addLinefungsi $scope.lineTextini undefined, ini dapat diatasi dengan menambahkan ng-controller="HomeCtrl"ke partial1.html, namun hal itu menyebabkan controller untuk dipanggil dua kali. Apa yang kulewatkan di sini?

Shlomi Schwartz
sumber

Jawaban:

83

Ini karena ng-includeyang menciptakan ruang lingkup anak baru, jadi $scope.lineTexttidak berubah. Saya pikir itu thismengacu pada ruang lingkup saat ini, jadi this.lineTextharus ditetapkan.

Renan Tomal Fernandes
sumber
260

Seperti yang disebutkan @Renan, ng-include membuat ruang lingkup anak baru. Lingkup ini mewarisi secara prototipik (lihat garis putus-putus di bawah) dari lingkup HomeCtrl. ng-model="lineText"sebenarnya menciptakan properti lingkup primitif pada lingkup anak, bukan lingkup HomeCtrl. Ruang lingkup anak ini tidak dapat diakses oleh lingkup induk / HomeCtrl:

ng-sertakan ruang lingkup

Untuk menyimpan apa yang diketik pengguna ke array $ scope.lines HomeCtrl, saya sarankan Anda meneruskan nilai ke fungsi addLine:

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

Selain itu, karena lineText dimiliki oleh lingkup / parsial ngInclude, saya merasa itu harus bertanggung jawab untuk membersihkannya:

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

Fungsi addLine () akan menjadi:

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

Biola .

Alternatif:

  • mendefinisikan properti objek pada $ lingkup HomeCtrl ini, dan menggunakannya dalam parsial: ng-model="someObj.lineText; biola
  • tidak dianjurkan, ini lebih dari hack: penggunaan $ orangtua dalam parsial untuk membuat / akses sebuah lineTextproperti di HomeCtrl $ lingkup:   ng-model="$parent.lineText"; biola

Agak terlibat untuk menjelaskan mengapa dua alternatif di atas bekerja, tetapi sepenuhnya dijelaskan di sini: Apa nuansa prototipal lingkup / warisan prototipikal di AngularJS?

Saya tidak merekomendasikan menggunakan thisfungsi addLine (). Semakin tidak jelas cakupan mana yang sedang diakses / dimanipulasi.

Mark Rajcok
sumber
1
Akhirnya saya mengerti.
Scott Tesler
1
Pertanyaan yang sama dengan @Jess, mengapa ini dianggap sebagai retasan?
qbert65536
13
@ qbert65536, ini pada dasarnya adalah hack / rapuh karena jika Anda merestrukturisasi HTML Anda, itu mungkin tidak berfungsi lagi. Misalnya, Anda mungkin perlu menggunakannya $parent.$parent...untuk membuatnya bekerja. Dengan kata lain, menggunakan $parentmembuat asumsi tentang struktur DOM.
Mark Rajcok
6
Tautan @Jess 'di atas telah diubah ke ng Lingkup Pengertian ini . Baca seluruh halaman, ini bagus.
mraaroncruz
1
Ini adalah jawaban yang sangat terperinci, tetapi saya mencoba semuanya tanpa hasil. Saya memiliki formulir dengan beberapa input ke controller dan hasil controller harus dilihat pada div lain. Setelah saya memasukkan input apa pun, sinkronisasi akan hilang dan saya akan memiliki nilai 0,00 konstan pada tampilan div saat aplikasi sedang berjalan.
zahra
33

Alih-alih menggunakan thisseperti saran yang diterima, gunakan $parentsebagai gantinya. Jadi di dalam kamu, partial1.htmlkamu akan memiliki:

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

Jika Anda ingin mempelajari lebih lanjut tentang ruang lingkup dalam ng-includeatau arahan lain, lihat ini: https://github.com/angular/angular.js/wiki/Understanding-Scopes#ng-include

ErwinGO
sumber
1
Bagi pembaca mana pun, maksudnya $scope.$parentalih-alih $parenttidak ditentukan menurut Angular.
Sebastialonso
1
Jawaban ini menyelamatkan saya! Terima kasih banyak telah menunjukkan penggunaan $ parent.
Derek Webb
itu $ scope. $ parent lulus dengan referensi? atau itu hanya salinan orang tua?
OMGPOP
1
@Sebastiallonso salah. $ scope. $ parent.lineText tidak terdefinisi. $ parent.lineText berfungsi, this.lineText atau cukup lineText juga berfungsi
OMGPOP
Yang $scope.$parentbekerja untuk saya di sudut 1.3.20
radtek
4

Saya telah menemukan cara untuk mengatasi masalah ini tanpa mencampurkan data induk dan sub lingkup. Setel ng-ifpada ng-includeelemen dan setel ke variabel lingkup. Sebagai contoh :

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

Di controller Anda, ketika Anda telah mengatur semua data yang Anda butuhkan di sub lingkup Anda, kemudian atur show to true. The ng-includeakan menyalin pada saat ini kumpulan data dalam lingkup Anda dan meletakkannya di sub lingkup Anda.

Aturan praktisnya adalah untuk mengurangi data lingkup yang lebih dalam lingkup, jika tidak, Anda memiliki situasi ini.

Maks

wascou
sumber
Saya menggunakan pendekatan ini untuk masalah yang serupa tetapi tidak sesuai untuk semua kasus. Terutama ketika Anda ingin elemen yang disertakan tidak pernah disembunyikan ...
iSpithash