buka kembali dan tambahkan dependensi ke aplikasi yang sudah di-bootstrap

89

Apakah ada cara untuk memasukkan ketergantungan terlambat ke modul sudut yang sudah di-bootstrap? Inilah yang saya maksud:

Misalnya saya memiliki aplikasi sudut lebar situs, yang didefinisikan sebagai:

// in app.js
var App = angular.module("App", []);

Dan di setiap halaman:

<html ng-app="App">

Nanti, saya membuka kembali aplikasi untuk menambahkan logika berdasarkan kebutuhan halaman saat ini:

// in reports.js
var App = angular.module("App")
App.controller("ReportsController", ['$scope', function($scope) {
  // .. reports controller code
}])

Sekarang, mengatakan bahwa salah satu dari mereka on-demand bit logika juga membutuhkan dependensi mereka sendiri (seperti ngTouch, ngAnimate, ngResource, dll). Bagaimana saya bisa melampirkannya ke Aplikasi dasar? Ini sepertinya tidak berhasil:

// in reports.js
var App = angular.module("App", ['ui.event', 'ngResource']); // <-- raise error when App was already bootstrapped

Saya menyadari bahwa saya dapat melakukan segalanya sebelumnya, yaitu -

// in app.js
var App = angular.module("App", ['ui.event', 'ngResource', 'ngAnimate', ...]);

Atau tentukan sendiri setiap modul, lalu masukkan semuanya ke dalam aplikasi utama ( lihat di sini untuk lebih lanjut ):

// in reports.js
angular.module("Reports", ['ui.event', 'ngResource'])
.controller("ReportsController", ['$scope', function($scope) {
  // .. reports controller code
}])

// in home.js
angular.module("Home", ['ngAnimate'])
.controller("HomeController", ['$scope', '$http', function($scope, $http){
  // ...
}])

// in app.js, loaded last into the page (different for every page that varies in dependencies)
var App = angular.module("App", ['Reports', 'Home'])

Tapi ini akan mengharuskan saya menginisialisasi App setiap saat dengan dependensi halaman saat ini.

Saya lebih suka untuk menyertakan dasar app.jsdi setiap halaman dan hanya memperkenalkan ekstensi yang dibutuhkan untuk setiap halaman ( reports.js, home.js, dll), tanpa harus merevisi bootstrap logika setiap kali saya menambahkan atau menghapus sesuatu.

Adakah cara untuk memperkenalkan dependensi saat Aplikasi sudah di-bootstrap? Apa yang dianggap sebagai cara (atau cara) idiomatik untuk melakukan ini? Saya condong ke solusi yang terakhir, tetapi ingin melihat apakah cara yang saya jelaskan juga dapat dilakukan. Terima kasih.

sa125
sumber
Bisakah Anda memberi saya kode kerja terakhir Anda, untuk dilihat?
Mangu Singh Rajpurohit
@ user2393267 mmm, sudah lama sekali, saya tidak tahu apakah saya masih memiliki kode itu ... Maaf. Saya pikir saya akhirnya meninjau kembali desainnya, karena biasanya ketika saya harus meretas hal-hal itu berarti saya tidak melakukannya dengan benar ... Namun, jika Anda masih bertekad untuk mengejar pendekatan ini, jawaban di bawah ini sepertinya petunjuk yang baik .
sa125

Jawaban:

115

Saya menyelesaikannya seperti ini:

referensi aplikasi lagi:

var app = angular.module('app');

lalu dorong persyaratan baru Anda ke larik persyaratan:

app.requires.push('newDependency');
AlBaraa Sh
sumber
3
Ini bekerja untuk saya +1 Saya menggunakan ini untuk beberapa ketergantungan al seperti app.requires.push ('doctorCtrl', 'doctorService');
Amir
8
Ini menyelamatkan arsitektur saya.
Saeed Neamati
3
Ini tidak berhasil untuk saya. Saya menambahkan ketergantungan secara dinamis seperti yang dijelaskan, tetapi Angular masih tidak dapat menemukan layanan dari modul yang ditambahkan.
Slava Fomin II
6
Dan app.requiresmerupakan sebuah array, jadi jika Anda menambahkan beberapa dependensi (seperti dalam contoh Laporan Anda), Anda meneruskannya sebagai argumen terpisah ke pushmetode: app.requires.push('ui.event', 'ngResource');atau jika dependensi tambahan Anda sudah menjadi sebuah array:Array.prototype.push.apply(app.requires, ['ui.event', 'ngResource'])
The Red Pea
2
Saya terkadang melewatkan pemungutan suara karena saya tidak ingin masuk, tidak kali ini! Terima kasih!
CularBytes
12

Sederhana ... Dapatkan contoh modul menggunakan getter seperti ini: var app = angular.module ("App");

Kemudian tambahkan ke koleksi "memerlukan" seperti ini: app.requires [app.requires.length] = "ngResource";

Bagaimanapun, ini berhasil untuk saya. SEMOGA BERHASIL!

David Donovan
sumber
4
Itu berhasil untuk saya! Saya punya pertanyaan - mengapa tidak menggunakan: app.requires.push ("ngResource")?
Philipp Munin
9

Menurut proposal ini di grup google Angular JS, fungsi ini tidak ada untuk saat ini. Mudah-mudahan tim inti memutuskan untuk menambahkan fungsi ini, bisa menggunakannya sendiri.

Matt Nibecker
sumber
4
Ya, ini sepertinya sangat berguna bagi orang yang belum tentu ingin membangun SPA.
regularmike
4

Jika Anda ingin menambahkan beberapa dependensi sekaligus, Anda dapat meneruskannya dalam push seperti berikut:

<script>
    var app = angular.module('appName');
    app.requires.push('dependencyCtrl1', 'dependencyService1');
</script>
Amir
sumber
4

Saya menyadari bahwa ini adalah pertanyaan lama, namun, belum ada jawaban yang berfungsi, jadi saya memutuskan untuk membagikan bagaimana saya menyelesaikannya.

Solusinya membutuhkan forking Angular, jadi Anda tidak bisa menggunakan CDN lagi. Namun modifikasinya sangat kecil, jadi saya heran kenapa fitur ini tidak ada di Angular.

Saya mengikuti tautan ke grup google yang disediakan di salah satu jawaban lain untuk pertanyaan ini. Di sana saya menemukan kode berikut, yang memecahkan masalah:

instanceInjector.loadNewModules = function (mods) {
  forEach(loadModules(mods), function(fn) { instanceInjector.invoke(fn || noop); });
};

Ketika saya menambahkan kode ini ke baris 4414 di kode sumber 1.5.0 sudut (di dalam createInjectorfungsi, sebelum return instanceInjector;pernyataan), itu memungkinkan saya untuk menambahkan dependensi setelah bootstrap seperti ini $injector.loadNewModules(['ngCookies']);.

tjespe
sumber
? Apa yang salah dengan jawaban pilihan tertinggi (per 26/6/2017) ? Sepertinya ini diberikan lebih dari setahun sebelum Anda memposting ini; apakah jawaban Anda memiliki beberapa keuntungan?
The Red Pea
@TheRedPea Yah tidak ada yang salah dengan itu, kecuali itu tidak menyelesaikan masalah saya, tetapi jawaban ini berhasil
tjespe
Dan itu tidak berhasil untuk Anda karena, saya menduga, Anda telah mem-boot aplikasi Anda? Saya mengamati itu juga ...
The Red Pea
2
Setelah membaca postingan Komunitas Google yang ditautkan, saya semakin yakin bahwa bootstrap adalah alasan mengapa solusi seperti ini diperlukan. Upvoting karena pertanyaan asli menanyakan tentang "aplikasi yang sudah di-bootstrap", yang tidak ada orang lain yang menjawab (memang OP mungkin salah bicara)
The Red Pea
1

Sejak versi 1.6.7 sekarang dimungkinkan untuk memuat modul secara lambat setelah aplikasi di-bootstrap menggunakan $injector.loadNewModules([modules]). Di bawah ini adalah contoh yang diambil dari dokumentasi AngularJS:

app.factory('loadModule', function($injector) {
   return function loadModule(moduleName, bundleUrl) {
     return getScript(bundleUrl).then(function() { $injector.loadNewModules([moduleName]); });
   };
})

Silakan baca dokumentasi lengkap tentang loadNewModules karena ada beberapa masalah di sekitarnya.

Ada juga aplikasi contoh yang sangat bagus dengan omkadiri yang menggunakannya dengan ui-router.

Denis Pshenov
sumber