Angularjs, melewatkan cakupan antar rute

87

Saya memiliki situasi dengan formulir yang membentang di beberapa halaman (mungkin tidak ideal, tetapi begitulah adanya). Saya ingin memiliki satu ruang lingkup untuk seluruh formulir yang terisi saat Anda melakukannya, sehingga jika pengguna bolak-balik di antara langkah-langkah tersebut, mudah untuk mengingat statusnya.

Jadi yang perlu saya lakukan, dengan sangat-pseudo-code:

  1. Set $scope.val = <Some dynamic data>
  2. Klik link dan diarahkan ke template baru (mungkin dengan pengontrol yang sama).
  3. $scope.val harus tetap memiliki nilai yang sama seperti di halaman terakhir.

Apakah data yang disimpan untuk cakupan adalah cara yang tepat untuk melakukan hal ini, atau adakah cara lain? Bisakah Anda bahkan membuat pengontrol yang memiliki cakupan tetap di antara rute, kecuali untuk menyimpannya dalam database tentunya.

Erik Honn
sumber
Hanya sebagai tambahan untuk ganaraj: Di sini Anda menemukan entri blog yang sangat bagus dengan screencast tentang cara mendapatkan pengontrol yang berbeda untuk berkomunikasi. Ada juga beberapa jsfiddles yang berguna untuk dimainkan. onehungrymind.com/angularjs-communicating-between-controllers Saya harap ini membantu.
F Lekschas

Jawaban:

138

Anda perlu menggunakan layanan karena layanan akan bertahan sepanjang hidup aplikasi Anda.

Katakanlah Anda ingin menyimpan data yang berkaitan dengan pengguna

Ini adalah cara Anda mendefinisikan layanan:

app.factory("user",function(){
        return {};
});

Di pengontrol pertama Anda:

app.controller( "RegistrationPage1Controller",function($scope,user){
    $scope.user = user;
    // and then set values on the object
    $scope.user.firstname = "John";
    $scope.user.secondname = "Smith";
});

app.controller( "RegistrationSecondPageController",function($scope,user){
        $scope.user = user;
        // and then set values on the object
        $scope.user.address = "1, Mars";

    });
Ganaraj
sumber
6
Ahhh! Saya mencobanya sebelumnya tetapi tidak dapat membuatnya berfungsi karena saya menggunakan pengontrol yang sama untuk kedua rute, jadi pada setiap rute baru nilai default akan menimpa nilai yang telah saya masukkan di halaman sebelumnya. Dengan dua pengontrol, atau tanpa nilai default, ini tidak lagi terjadi. Terima kasih!
Erik Honn
1
Apa tentang Value Recipe docs.angularjs.org/guide/providers , seperti myApp.value('clientId', 'a12345654321x');apakah itu juga tetap ada di antara rute?
The Bndr
@TheBndr: Seharusnya begitu. Nilai hanyalah bentuk layanan khusus yang saya pahami.
Robert Koritnik
3
Layanan tidak akan menyimpan data jika Anda memuat ulang halaman ... Jadi jika Anda berada di halaman 4 formulir Anda dan memuat ulang halaman itu, Anda akan kehilangan semua data yang telah diisi.
danielrvt
1
Jawaban bagus! Sebagai poin tambahan, panduan gaya bagi mereka yang mengambil jawaban ini - layanan yang bukan konstruktor (digunakan sebagai XX baru) harus diberi nama unta huruf kecil: github.com/mgechev/angularjs-style-guide .
Matt Byrne
9

Layanan akan berfungsi, tetapi cara logis untuk melakukannya hanya dengan menggunakan cakupan dan pengontrol biasa adalah dengan menyiapkan pengontrol dan elemen Anda sehingga mencerminkan struktur model Anda. Secara khusus, Anda memerlukan elemen induk dan pengontrol yang menetapkan lingkup induk. Halaman individu dari formulir harus berada dalam tampilan yang merupakan turunan dari induknya. Cakupan induk tetap ada bahkan saat tampilan anak diperbarui.

Saya berasumsi Anda menggunakan ui-router sehingga Anda dapat memiliki tampilan bernama bersarang. Kemudian di pseudo-code:

<div ng-controller="WizardController">
  <div name="stepView" ui-view/>
</div>

Kemudian WizardController menentukan variabel cakupan yang ingin Anda pertahankan di seluruh langkah formulir multi-halaman (yang saya sebut sebagai "wizard"). Kemudian rute Anda stepViewhanya akan diperbarui . Setiap langkah dapat memiliki template, pengontrol, dan cakupannya sendiri, tetapi cakupannya hilang dari halaman ke halaman. Tapi cakupan di WizardController dipertahankan di semua halaman.

Untuk mengupdate cakupan WizardController dari pengontrol anak, Anda harus menggunakan sintaks seperti $scope.$parent.myProp = 'value'atau menentukan fungsi setMyPropdi WizardController untuk setiap variabel cakupan. Jika tidak, jika Anda mencoba menyetel variabel lingkup induk langsung dari pengontrol anak, Anda akan berakhir hanya membuat variabel lingkup baru pada anak itu sendiri, membayangi variabel induk.

Agak sulit untuk dijelaskan dan saya mohon maaf atas kurangnya contoh lengkap. Pada dasarnya Anda menginginkan pengontrol induk yang menetapkan lingkup induk, yang akan dipertahankan di semua halaman formulir Anda.

tksfz.dll
sumber
1
Ini akan bekerja dengan ui-router ya (dan ini adalah cara yang cukup bagus untuk mendesain halaman seperti itu), tetapi tidak di luar kotak. Di luar kotak metode layanan adalah cara terbaik.
Erik Honn
1
Hanya untuk memperjelas, properti lingkup induk akan selalu diwarisi oleh lingkup anak. Namun, jika Anda ingin menyetel properti lingkup induk dari lingkup anak Anda perlu mengaksesnya di induk, jika tidak, Anda membuat properti baru dengan nama yang sama pada lingkup anak. Menetapkan properti lingkup induk dapat dilakukan dengan pergi:$scope.$parent.myProp = 'hello world';
mbursill
1
Ini adalah pendekatan yang jauh lebih baik daripada menggunakan layanan. Layanan adalah lajang, jadi setiap negara yang didefinisikan di sana bersifat global untuk aplikasi. Jika pengguna keluar dari wizard sebagian, kemudian memulainya kembali, akan ada status yang tersisa dalam layanan dari proses sebelumnya - kecuali Anda memastikan Anda membersihkan layanan dengan benar di setiap titik keluar, tetapi ini bisa cukup mudah menjadi sakit kepala perawatan yang substansial!
Dan King
Jauh lebih tertarik pada jawaban ini
Kurai Bankusu
Layanan adalah hal pertama yang terlintas dalam pikiran jika Anda tidak menggunakan Router UI Angular. Jika Anda menggunakan Router UI, ia memiliki penyelesaian bersarang yang dapat mempertahankan informasi di antara tampilan bersarang. Saya pikir itu akan menjadi pendekatan yang lebih bersih daripada mencoba mengakses cakupan orang tua. medium.com/opinionated-angularjs/…
losmescaleros
5

Data dapat dikirimkan antar pengontrol melalui dua cara

  1. $rootScope
  2. Model

Contoh di bawah ini menunjukkan penerusan nilai menggunakan model

app.js

angular.module('testApp')
  .controller('Controller', Controller)
  .controller('ControllerTwo', ControllerTwo)
  .factory('SharedService', SharedService);

SharedService.js

function SharedService($rootScope){

 return{
    objA: "value1",
    objB: "value2"
  }
}

// Ubah nilai dalam pengontrol A

Controller.js

function Controller($scope, SharedService){

 $scope.SharedService = SharedService;

 $scope.SharedService.objA = "value1 modified";
}

// Akses nilai di controllertwo

ControllerTwo.js

function ControllerTwo($scope, SharedService){

 $scope.SharedService = SharedService;

 console.log("$scope.SharedService.objA"+$scope.SharedService.objA); // Prints "value1 modified"
}

Semoga ini membantu.

DILIP KOSURI
sumber