1

I'm facing an interesting issue here.

I'm developing a Chrome Extension with a content script.

This extension is intended to add a little div to a page, this div using AngularJS. (I chose Angular because I want this div's data to be readily updated by change of var values).

I'm able to add the div once and bootstrap it. So the behavior of the div is fine.

But the main page (which I have no control over) often reloads everything using Ajax. (Then I'm totally unable - I think - to get events from certain elements being removed).

I was able to create ways to check if my elements are still on the page, and if not, they are added again. The appendChildPersistent method takes care of it. (It waits for a certain element to appear on the main page. Adds my element to it. Runs the callback when added. Keep checking if the element is still there, if not, repeat all over).

So all my ordinary elements work perfectly.

But this angular div cannot be bootstraped a second time.

Procedures:

  • I wait until a certain element appear on the main page
  • I add my own div myDiv from a plain text html using jquery append to the main page div
  • I load the angular application and bootstrap it using the callback function when the div is added:

Code:

var txt = '<div id="myDivId" ng-controller="myController">{{testing}}</div>';

appendChildPersistent('myDivId', MyDiv, '#theTargetMainPageDiv', function()
{
        var app = angular.module('myApp', [])
            .controller('myController', function($scope) {
                $scope.testing = 'Welcome!';
            });

        angular.bootstrap(document, ['myApp']);
});

So, the first time my div is added, it works. The angular vars and directives work (in this example, the div shows "Welcome!"). But the second time, I get an "already bootstrapped" error. (But if I do not try to bootstrap again, the div becomes just plain text, no angular behavior, showing "{{testing}}" instead of "Welcome!").

Is there a way to unboostrap, redo bootstrap or another method I could work to get around this?

Daniel Möller
  • 84,878
  • 18
  • 192
  • 214
  • You bootstrap the whole document. You have to bootstrap your div. – a better oliver Jun 28 '15 at 20:32
  • Ok!!! If you mind to add that as an answer, it will be accepted :) – Daniel Möller Jun 28 '15 at 21:12
  • _"I was able to create ways to check if my elements are still on the page, and if not, they are added again."_ Consider using something like [mutation-summary](https://github.com/rafaelw/mutation-summary) for this. – Xan Jun 29 '15 at 09:00
  • Thanks, @Xan, but that would be rather complex compared to what I managed to do, because it's an overkill. I made it very simple [here](http://stackoverflow.com/questions/31073493/insert-content-script-when-page-was-changed-by-history-pushstate-and-ajax-call/31106499#31106499) - I'm aware of a possible issue when trying to add many elements to the same target, but it's an easy fix. – Daniel Möller Jun 29 '15 at 14:40
  • It's an imperfect fix, since with poll-based detection there's always a possibility of delay until something is detected, and a possibility that most polls will be just a waste of CPU cycles. – Xan Jun 29 '15 at 14:41
  • I understand your point. But for my personal use it's totally ok. That little delay is compared to those of the dynamic elements being loaded. I should consider sometime in the future to keep only one timer for all the elements added that way. – Daniel Möller Jun 29 '15 at 14:46

1 Answers1

2

Your application only focuses on the div you insert. You can make an Angular application run on a certain area of the page instead of covering the whole document. Simply pass the DOM element to the bootstrap function:

angular.bootstrap(myDiv, ['myApp']);

This way Angular only runs in your div and you are able to bootstrap the app every time you add a new div.

a better oliver
  • 26,330
  • 2
  • 58
  • 66