Josh Petitt
Josh Petitt

Reputation: 9579

angularjs test if file exists for ng-include

I am using ng-include to bring in a partial in an AngularJS app. If the partial .html file doesn't exist, I would like to do something else.

The partial name is extracted from the $location.path(). So if the path is "/foo", then I would like use "my_partial_foo.html". However if "my_partial_foo.html" doesn't exist, then I'd like to use "my_partial_default.html" instead.

I'm putting this data into a $dialog, so I can't use the typical routeProvider functionality (afaik).

My main question is: How do I determine if "my_partial_foo.html" exists before I use it in an ng-include directive?

Related questions:

angular - reusable dialogs

How to prepopulate a dialog in angularjs/bootstrap

Upvotes: 5

Views: 8481

Answers (2)

jusopi
jusopi

Reputation: 6813

I had a similar need but found the built-in $templateCache & ui.router's $templateFactory to have inconsistent behavior. When I'd use this...

$templateFactory.fromUrl( './non-existant.html' )
.catch( function( err ){ console.log( 'does not exist' )})

...it would fail to trigger the catch callback. It was only after hitting this call twice would the error get triggered.

So I rolled my own solution using $q and XMLHttpRequest:

.service( 'templateUtils', [
    '$q'
    function( $q ){
        var api = {
             hasTemplate: function( url ){
                  var d = $q.defer()
                  var rqst = new XMLHttpRequest()
                  rqst.open( 'GET', url )
                  rqst.onload = function( evt ){
                       if( evt.target.status === 200 )
                           d.resolve( true )
                       else
                           d.reject( false )
                  } 

                  return d.promise
             }
        }

        return api
    }
])

I use this like so...

var templateUrl = './default-template.html'

templateUtils.hasTemplate( urlToCheck )
.then( function( rsp ){ templateUrl = './different-template.html' })

Upvotes: 1

mdonovan2010
mdonovan2010

Reputation: 423

Something like this might work. Basically the $templateCache will always have a key for my_partial_foo.html (so your ng-include can always reference it) but the value might be the default or the real thing.

var app = angular.module('myapp', []).run(function($templateCache,$http){
  $http.get('my_partial_foo.html',
    //success
    function(data){
      $templateCache.put('my_partial_foo.html', data);
    },
    //failure
    function(){
      $http.get('my_partial_default.html', function(data){
        $templateCache.put('my_partial_foo.html', data);
      });
    });
});

Upvotes: 3

Related Questions