Compile an HTML template and initiate a printing operation only once the compilation process has finished

While working on a directive's link function, my goal is to insert a compiled ad-hoc template into the DIV of a document and then proceed to print the window. I attempted the code below, and although the printer preview shows up, the data in it is still uncompiled.

// create a div
printSection = document.createElement('div');
printSection.id = 'printSection';
document.body.appendChild(printSection);

// Attempting to add a template to the div
scope.someVar = "This is print header";
var htmlTemplate = "<h1>{{someVar}}</h1>"; 
var ps = angular.element(printSection);
ps.append(htmlTemplate);
$compile(ps.contents())(scope);

// How can I ensure that the content inside printSection gets compiled properly 
// (I will eventually need to render a table using ng-repeat)

window.print();
// ... currently displays page with "{{someVar}}", instead of "This is print header"

I also wonder if $compile operates asynchronously? Can someone guide me on how to trigger window.print() only after compilation is complete?

Answer №1

To be able to print, you just need to finish the current digestion process.

Instead of using window.print();, try using:

_.defer(function() {
    window.print();
});

or utilize $timeout, or any deferred handler.

Another approach (likely the 'correct' method) is to ensure that the newly compiled content's watchers execute before exiting the current $apply phase :

module.factory("scopeUtils", function($parse) {

        var scopeUtils = {

            /**
             * Apply watchers of given scope even if a digest progress is already in process on another level.
             * This will only do a one-time cycle of watchers, without cascade digest.
             *
             * Please note that this is (almost) a hack, behavior may be hazardous so please use with caution.
             *
             * @param {Scope} scope : scope to apply watchers from.
             */
            applyWatchers : function(scope) {
                scopeUtils.traverseScopeTree(scope, function(scope) {
                    var watchers = scope.$$watchers;
                    if(!watchers) {
                        return;
                    }
                    var watcher;
                    for(var i=0; i<watchers.length; i++) {
                        watcher = watchers[i];
                        var value = watcher.get(scope);
                        watcher.fn(value, value, scope);
                    }
                });
            },

            traverseScopeTree : function(parentScope, traverseFn) {
                var next,
                    current = parentScope,
                    target = parentScope;
                do {
                    traverseFn(current);

                    if (!(next = (current.$$childHead ||
                        (current !== target && current.$$nextSibling)))) {
                        while(current !== target && !(next = current.$$nextSibling)) {
                            current = current.$parent;
                        }
                    }
                } while((current = next));
            }

        };

        return scopeUtils;
    });

Usage example:

scopeUtils.applyWatchers(myFreshlyAddedContentScope);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular: Incorporate a unique random number into each request to prevent caching in Internet Explorer

In Internet Explorer, there is a significant issue with caching xhr requests as discussed here. One suggested solution is to add a random number to the url, as shown here. While this workaround can be effective on an individual basis, I am seeking a more ...

Upgrade from AngularJS to the latest version of Angular, version 8

I'm trying to convert this AngularJS code into Angular 2+, but I'm having some trouble. Any ideas on how to do it? I've searched around, but this specific line is confusing me. scope.variable.value = event.color.toHex() Old Code: functi ...

Guide on creating a custom directive called 'ng-let' to associate an expression with a variable

If I want to create a custom directive that functions like ng-repeat but assigns a name to a single variable: instead of writing code like this: ng-repeat="summary in data.accounts.all.summaryAsArray()" I could write something similar to this: ng-let=" ...

Leveraging ng-switch for template swapping

I'm currently facing an issue in my Angular app where I want to switch from a "sign in" form to a "sign up" form when the user clicks on the "Sign Up" button, but nothing happens upon clicking the button. The sign-in form persists on the screen withou ...

Tips for Implementing {{ }} within Angular Filters in Nested ng-repeat statements

I am looking to incorporate {{ }} within the Angular "filter" filter, specifically while nested inside an ng-repeat. Let's consider the relationship below: var categories = [ {"title":"land"}, {"title":"sea"}, {"title":"air"} ]; var vehi ...

Create a tab layout in Ionic Framework that closely resembles the design and

For my latest project, I decided to use Ionic but I found the UX for iOS lacking. Is there a way to customize the tabs design (see picture) instead of using the basic tab layout that Ionic provides when creating a tab project? Click here to see image ...

The AngularJS OpenLayers directive encounters issues when used inside an Angular-UI dialog component

I am interested in integrating the AngularJS OpenLayers directive into my webpage. It seems to work fine on its own, but when I try to use it within angular-ui-dialog, it does not function. Despite checking the console for errors, I am unable to determine ...

Shut down the angular modal

I am currently learning AngularJS and I find myself working on an application that utilizes both angular modal and jqGrid. (I understand this may not be the ideal setup, but for now, I have to make it work with both.) The content of my modal is loaded usi ...

The processed value is not immediately returned by DataSnapshot.val()

Here is a function defined within a factory: kbUser.getCurrentUserDetails = function(){ return $rootScope.ref.child("user/" + firebase.auth().currentUser.uid).once('value', function(snap){ return snap.val(); }); } In a controlle ...

Encountering a 405 Method Not Allowed error when using Laravel in conjunction with AngularJS

After successfully setting up Laravel Homestead and AngularJS, I am encountering an issue when trying to POST or GET data from the Laravel API using the Angular app. The errors displayed in the Firefox inspector Network tab include: 405 Method Not Allowed ...

Tips for creating an array within an AngularJS Service and effectively sharing it across two controllers

I have two controllers, FirstController and SecondController, along with a service defined as follows: app.factory('Data', function(){ return []; }); In both controllers, I am utilizing the service in this manner: app.controller("FirstCont ...

Sorting and filtering data using AngularJS filter and orderBy inside a controller or factory

I am currently working with a factory that looks like this: app.factory("ModuleFactory", function (api, $http, $q, filterFilter) { var moduleList = []; var categoryList = []; var moduleTypeList = []; var academyModuleTypeList = []; var mostUsed = []; var ...

The AngularJS upload function is returning false when checking Request.Content.IsMimeMultipartContent

I am facing an issue while trying to upload files along with form data from my Angularjs client to a web api. I came across some reference code online and followed the same approach. However, when I execute the first line of code in the Web API method, if ...

Unexpected behavior encountered when using the $http.post method

I've been working with a component that I utilized to submit data to the Rest API. The code snippet for the component is as follows: (function(angular) { 'use strict'; angular.module('ComponentRelease', ['ServiceR ...

AngularJS view not properly refreshing after async operation completes

There is a factory in my application that retrieves data from the server and passes it to multiple controllers. However, only the scope variable of the controller that calls the factory first gets updated in the view. Here is the code snippet for the facto ...

Challenges arise when attempting to store data from a Form into a mongodb collection

I am currently in the process of developing an application using the MEAN stack. For my MongoDB database schema, I am utilizing mongoose. However, I have encountered issues when attempting to save data into a collection that includes String, Number, and Da ...

Invoking a Directive within another Directive

Feel free to check out this demo on Plunkr. I've set up a basic structure: <body ng-app="myApp"> <div ng-controller="myController"> <parent-directive></parent-directive> <child-directive></child-direc ...

"Permission denied to access restricted URI" error encountered while attempting to utilize ng-template functionality

I am attempting to implement ng-include for recursive templates in my HTML. After testing it on jsfiddle and confirming that it works, I tried the same locally. However, I encountered the following error: Error: Access to restricted URI denied createHttpB ...

The calendar fails to display events once the $scope.splice(0) and $scope.push(event) functions are executed

Greetings, I am encountering an issue with the angular ui-calendar (angular wrapper for arshaw's fullcalendar). Initially, I load the events using a $http call in the first step and the calendar displays correctly. However, in the next step, when lo ...

Adjust the height of each child element to be half of the fixed height of the parent

There is a wrapper containing multiple boxes generated using ng-repeat from a list. The wrapper has a fixed height of 300px. If the list contains only one box, a class is added to fill the entire space of the wrapper. However, when there are more than on ...