Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS - How to modularize a directive + template combination?

Here's the situation. I have a directive, that depends on a templateUrl.

The directive looks something like this:

angular.module('foo')
.directive('bar', function(){
  return {
    restrict: 'E',
    replace: true,
    templateUrl: '/foo/bar.html',
    controller: 'fooController',
    require: '^ngModel',
    scope: {
      onSuccess: '&'
    }
  };
});

This directive is part of one of my applications, and it's important that it stays part of the application. However, I'd also like to use the same directive in other projects, and currently I'm using bower to pull down the repository into my other projects. However, this directive will break because the templateUrl will be incorrect. Bower clones down my entire project, and the actual path of the template, at best, will need to be this in my other project:

/lib/public/foo/bar.html

How do other people manage this?

like image 928
bioball Avatar asked Jun 04 '14 19:06

bioball


People also ask

Which directive initializes an AngularJS application?

The ng-app directive initializes an AngularJS application. The ng-init directive initializes application data. The ng-model directive binds the value of HTML controls (input, select, textarea) to application data.

Can we create custom directive in AngularJS True False?

AngularJS comes with a set of these directives built-in, like ngBind , ngModel , and ngClass . Much like you create controllers and services, you can create your own directives for AngularJS to use.

Which directive definition option is used to replace the current element if true?

As the documentation states, 'replace' determines whether the current element is replaced by the directive. The other option is whether it is just added to as a child basically.


2 Answers

I've never liked using template strings for templating due to issues with maintainability. I prototype html very quickly so I opt for a grunt task that reads my files and processes them into a single $templateCache js file.

Solution

Grunt Angular Templates

Grunt build task to concatenate & register your AngularJS templates in the $templateCache

// within my Gruntfile.js
grunt.initConfig({
  ngtemplates: {
    'angular-my-directives': {
      src:      'views/**/*.html', // where my view files are
      dest:     'src/templates.js' // single file of $templateCache
    }
  }
  // ...
});

generates something like: ./src/templates.js which preserves my folder structure:

angular.module('angular-my-directives').run(['$templateCache', function($templateCache) {

  $templateCache.put('views/directives/my-download.html',
    "<form name=\"myDownloadForm\" ng-submit=\"submit()\" novalidate>\n" +
    "</form>"
  );

}]);

Now in my directive I can simply use templateUrl: 'views/directives/my-download.html' and it will use the $templateCache.

Finally I used grunt-contrib-concat to combine my files for easy loading.

Checkout "Grunt concat + uglify with sourcemaps" (or leave a better link in comments) to learn about how to concat + uglify (aka min) js files into a single "dist" file.

If working on your own custom bower package..

Be sure to commit the concatenated (aka built) files to the package repo so your package consumers can simply include my-concat-package.js or my-concat-package.min.js

like image 176
electblake Avatar answered Sep 28 '22 05:09

electblake


Angular directives have templateUrl and template properties. template receives a HTML string. It's not a perfect solution, because you need to put HTML into your JS. But it is a common pattern for library creators to put the HTML string directly on template property, so they can wrap their module into a single file.

You may want make that templateUrl-to-template a build step of you lib.

Take a look on Angular Bootstrap Bower Repo.

like image 27
Ken Rosaka Avatar answered Sep 28 '22 03:09

Ken Rosaka