I'm attempting to follow this SO answer explaining how to render a recursive JSON structure using a directive. However, unlike the answer provided, my data is not known when the DOM is loaded and Angular runs for the first time.
Instead, my data is retrieved from an HTML input field and stored in an Angular Service (when the user submits the form).
How can I keep an Angular Directive up-to-date when the Service's data is modified?
Update in response to answer
@musically_ut provided an excellent answer that has helped, but revealed a related problem, preventing an implementation (updated here).
The directive renders HTML that contains Angular {{expressions}}
which access data stored in $scope
. Since the original solution was to $watch
when the service had it's data ready. How can I ensure the 'new' data is added to $scope
before the directive renders?
An overview of the architecture and flow is:
ControllerA
-> Get input from user ControllerA
-> Use service to transform data ControllerB
-> $watch
for changes in service
Directive
-> $watch
for changes in service
ControllerB
-> Add data to $scope
Directive
-> Display transformed data (from service) using
directives
The problem is between steps 5 and 6. The directive renders {{expressions}}
before ControllerB has added the data to $scope
. Even if this did work, it feels way too complex and 'hacky'.
In fact, to regress, I'm using $watch
in ControllerB to listen for when the transformed data is ready in a service. Even this feels a little overkill (the service makes no asynchronous calls).
Updating dependencies 6, change the versions of angular , angular-animate and angular-resource packages to 1.6. 6 in the dependencies section of the package. json file. Run npm install to ensure that the specified dependencies are downloaded into the application.
ngOnChanges()link A callback method that is invoked immediately after the default change detector has checked data-bound properties if at least one has changed, and before the view and content children are checked.
In a hybrid application you run both versions of Angular at the same time. That means that you need at least one module each from both AngularJS and Angular. You will import UpgradeModule inside the NgModule, and then use it for bootstrapping the AngularJS module.
You can inject the service while defining the directive and then set up a $watch
on the data. So in your case:
.directive('tree', function ($compile, myService) {
return {
// ...
link: function (scope, element, attrs) {
scope.$watch(function () {
return myService.getData();
},
function (newVal) {
if (typeof newVal !== 'undefined') {
// ...
}
}
});
}
});
This will watch the data for change and run the code each time the data changes.
However, if the data does not change after being set once, a better way (more efficient) would be to return a promise from the service ($http
methods returns a promise directly or you can create one using the $q
service) and then add your computation as a continuation to the data.
.directive('tree', function ($compile, myService) {
return {
// ...
link: function (scope, element, attrs) {
myService.getData().then(function (data) {
// ...
}, function (err) {
// Handle error
});
}
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With