To pytanie jest stare, ale długo walczyłem, próbując znaleźć odpowiedź na ten problem, który zadziałałby na moje potrzeby i niełatwo go znaleźć. Uważam, że moje następne rozwiązanie jest znacznie lepsze niż obecnie akceptowane, być może dlatego, że angular ma dodatkową funkcjonalność od czasu postawienia tego pytania.
Krótka odpowiedź przy użyciu metody Module.value pozwala przekazać dane do konstruktora kontrolera.
Zobacz mój plunker tutaj
Tworzę obiekt modelu, a następnie kojarzę go ze sterownikiem modułu, odnosząc go do nazwy „model”
HTML / JS
<html>
<head>
<script>
var model = {"id": 1, "name":"foo"};
$(document).ready(function(){
var module = angular.module('myApp', []);
module.value('model', model);
module.controller('MyController', ['model', MyController]);
angular.bootstrap(document, ['myApp']);
});
function confirmModelEdited() {
alert("model name: " + model.name + "\nmodel id: " + model.id);
}
</script>
</head>
<body >
<div ng-controller="MyController as controller">
id: {{controller.model.id}} <br>
name: <input ng-model="controller.model.name"/>{{controller.model.name}}
<br><button ng-click="controller.incrementId()">increment ID</button>
<br><button onclick="confirmModelEdited()">confirm model was edited</button>
</div>
</body>
</html>
Konstruktor w moim kontrolerze akceptuje następnie parametr o tym samym identyfikatorze „model”, do którego może uzyskać dostęp.
Kontroler
function MyController (model) {
this.model = model;
}
MyController.prototype.incrementId = function() {
this.model.id = this.model.id + 1;
}
Uwagi:
Korzystam z ręcznej inicjalizacji ładowania początkowego , co pozwala mi zainicjować mój model przed wysłaniem go pod kątem. To działa znacznie ładniej z istniejącym kodem, ponieważ możesz poczekać, aż skonfigurujesz odpowiednie dane i skompilujesz tylko część kątową aplikacji na żądanie, kiedy tylko zechcesz.
W plunkerze dodałem przycisk, aby zaalarmować wartości obiektu modelowego, który początkowo został zdefiniowany w javascript i przekazany do angular, tylko po to, aby potwierdzić, że angular naprawdę odnosi się do obiektu modelowego, zamiast kopiować go i pracować z kopią.
Na tej linii:
module.controller('MyController', ['model', MyController]);
Przekazuję obiekt MyController do funkcji Module.controller, zamiast deklarować jako funkcję wbudowaną. Myślę, że pozwala nam to na znacznie jaśniejsze zdefiniowanie naszego obiektu kontrolera, ale dokumentacja kątowa ma tendencję do robienia tego bezpośrednio, więc pomyślałem, że należy to wyjaśnić.
Używam składni „kontroler jako” i przypisuję wartości do właściwości „this” MyController, zamiast używać zmiennej „$ scope”. Sądzę, że działałoby to równie dobrze przy użyciu $ scope, przypisanie kontrolera wyglądałoby wtedy tak:
module.controller('MyController', ['$scope', 'model', MyController]);
a konstruktor kontrolera będzie miał taki podpis:
function MyController ($scope, model) {
Jeśli z jakiegoś powodu chcesz, możesz również dołączyć ten model jako wartość drugiego modułu, który następnie dołączasz jako zależność do modułu podstawowego.
Uważam, że jego rozwiązanie jest znacznie lepsze niż obecnie akceptowane, ponieważ
- Model przekazany do kontrolera jest w rzeczywistości obiektem javascript, a nie ciągiem podlegającym ocenie. Jest to prawdziwe odniesienie do obiektu, a zmiany w nim wpływają na inne odwołania do tego obiektu modelu.
- Angular mówi, że użycie ng-init przez zaakceptowaną odpowiedź jest niewłaściwym użyciem, czego nie rozwiązuje to rozwiązanie.
Sposób, w jaki Angular wydaje się działać w większości innych przykładów, które widziałem, ma kontroler definiujący dane modelu, co nigdy nie miało dla mnie sensu, nie ma oddzielenia między modelem a kontrolerem, co tak naprawdę nie wydaje się MVC do mnie. To rozwiązanie pozwala naprawdę mieć całkowicie oddzielny obiekt modelu, który przekazujesz do kontrolera. Warto również zauważyć, że jeśli zastosujesz dyrektywę ng-include, możesz umieścić cały kątowy HTML w osobnym pliku, całkowicie oddzielając widok modelu i kontroler na osobne moduły.