0

I am relatively new to angular and here is what I am trying to do:

I am trying to pre-compile angular templates into a view so that they can be shown instantaneously when the navigation event to the view occurs.

I am trying mock some kind of a navigation controller behavior for my app where the views preload or stack up and don't show in the SPA until their routes are active.

I did some research and $templateCache might not be something that would work for me since it seems to be only prefetching the template, viz. the uncompiled view (as per my limited understanding of angular), but what I am looking for is the "compiled version"; that is, the result of a $scope applied to a template.

Currently, the app's templates and controllers are linked through $routeProvider and ng-view constructs.

Minimal code skeleton:

JS:

var app = angular.module('airfiApp', ['ngRoute']);
app.config(function($routeProvider) {
    $routeProvider
        .when('/', {
            templateUrl: 'views/home.html',
            controller: ''
        })
        .when('/shop', {
            templateUrl: 'views/shop.html',
            controller: 'ShopController'
        })
        .otherwise({
            redirectTo: "/index.html"
        }))
});

app.controller('ShopController', ['ImageFetchService', function(ImageFetchService) {
    ImageFetchService.get().then(function(images) {
        $scope.images = images;
    });
}]);

app.factory('ImageFetchService', ['$q', '$http', function($q, $http) {
    var def = $q.defer();
    //basically get product docs with id products:name-of-product
    var couchdbURL = 'http://username:password@localhost:5984/db_name/_all_docs?startkey="products"&endkey="products\uffff"';
    $http.get(couchdbURL).then(function() {
        //do some processing and send back array of objects called 'images'
        /* images =
            [
                {
                    ... product information... ,
                    src: http://couchurl/db_name/product1/attachment_name

                },
                {
                    ... product information... ,
                    src: http://couchurl/db_name/product2/attachment_name

                }

                .
                .
                .
            ]
        */
        def.resolve(images)
    });
}]);

HTML:

//index.html
<!DOCTYPE html>
<html>
<head>
    <script src="/Scripts/angular.js"></script>
    <link href="/Content/bootstrap.css" rel="stylesheet"/>
</head>
<body>
<!-- some home page html -->
<section ng-view> </section>
</body>
</html>

//shop.html
<div ng-repeat = " img in images">
    <img ng-src="img.src" alt="img.productName" />
</div>
trk
  • 2,106
  • 14
  • 20
  • Please add an [mcve] to your question. It's hard to troubleshoot something like this without the specifics – blurfus Oct 20 '15 at 21:15
  • This feels like an XY problem to me. There have been plenty of people who have posted online alternatives to the way that angular loads templates and views, but what real world problem are you having that is causing you to try to create this solution? – Claies Oct 20 '15 at 21:18
  • @ochi okay, I shall create a trimmed working sample. The app fetches in some couchdb attachments into ng-src attributes of img tags. This takes a lot of time since its hitting the db. So, the idea was : why not prefetch this view and all the couchdb attachments it needs to show. – trk Oct 20 '15 at 21:20
  • are you using ui-router? – TimCodes Oct 20 '15 at 21:29
  • @TimCodes I am using routeProvider. I am not using stateProvider. – trk Oct 20 '15 at 21:35
  • @Claies this is a shopping app. the view under question is the catalog of products to sell. index.html is the homepage and the route where is view is located is /shop. Now, shop displays many products and product docs in couchdb has its images as attachments. The catalog does not change or is in other words relatively static, therefore I am trying to run the view but not show it until the route change is initiated by the user. Hope I answered your question ? – trk Oct 20 '15 at 21:37
  • 1
    are you planning on fetching the data from Couchdb as soon as the app loads? – TimCodes Oct 20 '15 at 21:38
  • @TimCodes yes now you read my mind. – trk Oct 20 '15 at 21:39
  • you already have a service/factory in place? – TimCodes Oct 20 '15 at 21:44
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/92909/discussion-between-82tuskers-and-timcodes). – trk Oct 20 '15 at 21:52

2 Answers2

0

I really don't think you need to compile the template manually - angular will do this for you. If you really insist, you can compile any template against any scope using $compile:

$compile( element.contents() )( scope );

What I really think you're after is loading of inline template. This question shows how it is done.

Community
  • 1
  • 1
Izhaki
  • 23,372
  • 9
  • 69
  • 107
  • yes you are right. May be I don't want to compile the template. I want to preload the view. Something like a "display: none, z-index: -1 (to hide it from the foreground)" and "display: block, z-index: 0/1" for the ng-view directive when shop is clicked. Basically I don't want to wait to load the couchdb attachments when user clicks instead I want to pre-populate them so the view will load faster from the browser cache. – trk Oct 20 '15 at 21:50
0

A couple things you can do to easily speed up how fast a view is rendered, first thing is you can pre-load the data by calling a pre-load method in a service, during the run phase of the App. Example

//service that has a preload function that stores an http result in memory
app.service('myService', function($http){
   var data;

   this.getData= function(){

   return  $http.get('dataUrl')
    .success(function(data, status, headers, config) {

       return data;
    })

  };

  // calls get data and stores result in memory
  this.preloadData = function(){

       this.getData().then(function(data){
       data = data; 

    });
  };

  // returns in memory result
  this.getPreloadedData = function(){

    return data;
  };
}); 

// call preload in run block 
app.run(function(myService){

  // preloads data from service  
  myService.preloadData();
});

// get data from in memory
app.controller('TestCtrl', function($scope, myService) {
  $scope.data = myService.getPreloadedData();
});

The second thing you can do is store the template in $template cache rather than fetching it form a http request, you can do this in the run block as well, and if you using gulp or grunt there are some great plug ins that provide a better way of doing this

app.run(function($templateCache){

  // cache template
    var tempalate = '<h2>hello world</h2>'
   $templateCache.put('test.html', tempalate);
}); 

here is a plunk that goes into better detail and shows more examples http://embed.plnkr.co/DSeWLVNoV2Fe0SJI3Bwa/preview

This does exactly preload the route but it will help performance :)

TimCodes
  • 365
  • 2
  • 14