3

I've seen a bunch of posts recommending using a directory per feature with angular. Today I've added RequireJS (AMD) to a new angular application I'm working on. I was using script tags at the end of the body tag, then I did some AMD restructuring and everything magically became 300% better.

It was all going great, the AMD style require supported relative paths when working with JS files, but with templateUrl, it starts at the root instead of in the directory I'm in. I've seen solutions like reading the "currently executing script file", I doubt that approach would work with AMD.

Is there a trick I don't know about to pass the path from somewhere? I don't mind doing some work per file, but I really don't want to do something like templateUrl: baseUrl + 'template.view1.html' everywhere I use templateUrl.

I'm using ui-router, if it matters (first day, yay).

Community
  • 1
  • 1
Madd0g
  • 3,841
  • 5
  • 37
  • 59

3 Answers3

1

What about using require.toUrl(...)

Take a look to the official docs: http://requirejs.org/docs/api.html#modulenotes-urls

leog
  • 778
  • 10
  • 15
0

I am using something like this

angular.module('...', ['...'])
    .constant('basePath', 'app/path/to/something/')

and later

templateUrl: basePath + 'morePath/myFile.html',
timtos
  • 2,225
  • 2
  • 27
  • 39
  • The good thing is, that you can use dependency injection. That is not visible in my three line sample but for the interested reader: http://stackoverflow.com/questions/17383611/angularjs-getting-module-constants-from-a-controller - and one side note: Of course it is also possible to use a factory and get a perhaps more dynamic value out of this. For me, the constant way worked smoothly. – timtos Nov 14 '14 at 08:50
  • I would have to remember to glue the base path to the relative path every time I use `templateUrl` *and* pass the path individually for each feature directory because I chose feature-oriented directory structure. I was hoping for something cleaner. – Madd0g Nov 14 '14 at 14:40
0

I have a little project, angular-require-lazy trying to mix RequireJS and Angular. In it I have written the templateCache AMD plugin, working as:

require(['templateCache!./navbar.html',...], function(navbarTemplate, ...) {...});

So, the proper template is loaded (using RequireJS's text! plugin under the hoods - so it is compilable with r.js too). The object you get (the navbarTemplate argument in the example above) has 2 properties, one is the actual loaded text and one the URL, under which the text is registered with Angular's templateCache. You can then use it as:

require(['templateCache!./navbar.html',...], function(navbarTemplate, ...) {
    ...
    // will give you the correct URL, with `./` expanded properly
    // the text is already registered with Angular
    templateUrl: navbarTemplate.path
    ...
});

Unfortunately, I haven't gotten into making angular-require-lazy compatible with ui-router yet, so you cannot use it as is. The code of the plugin (really small) might give you some idea for your own implementation of this feature:

define(["module", "./currentModule"], function(module, currentModule) {
    "use strict";

    /** RequireJS module loader entry point. */
    function load(name, parentRequire, onload, config) {
        parentRequire(["text!" + name], function(t) {
            if( !config || !config.isBuild ) {
                currentModule.run(["$templateCache", function($templateCache) {
                    $templateCache.put(name, t);
                }]);
            }
            onload({
                text: t,
                path: name
            });
        });
    }

    return {
        load: load
    };
});

(The currentModule is angular-require-lazy - specific, you will have to replace at least that with the current Angular module.)

Nikos Paraskevopoulos
  • 39,514
  • 12
  • 85
  • 90
  • this is a good method but I was really hoping to avoid polluting the top of the file with all these requires for templates. I realize now I can just make it work with relative paths with the `text!` plugin (I didn't know about it until now, I just started using r.js) – Madd0g Nov 14 '14 at 23:36
  • Yes, revisiting your case it may be enough to require the `text!./file.html` and then use it as `template: file`. – Nikos Paraskevopoulos Nov 15 '14 at 13:15