webpack with ocLazyload fails to load both controller and template files - javascript

var templatePath = require('../templatePath');
var controllerPath = require('../ControllerPath');
$scope.loadNgModules = function(templatePath, controllerPath) {
var files = [];
if (templatePath) files.push({ type: 'html', path: templatePath });
if (controllerPath) files.push({ type: 'js', path: controllerPath});
if (files.length) return $ocLazyLoad.load(files)
};
ocLazyLoad is not working When I use webpack for minification. Since I guess ocLazyLoad accepts only path of the template and controller but webpack is bundling both template and controller into the single minified file so it fails to load.
Webpack plugin name : uglifyjs-webpack-plugin'
Is there any way to accomplish this problem using ocLazyLoad.? Can I load a string of template and controller file other than considering path.?

As per my understanding basically ocLazyLoad accepts only path of the script and template files
So I have resolved this issue by using $templateCache
if (angular.isString(templatePath) && templatePath.length > 0) {
angular.forEach(angular.element(templatePath), function (node) {
if (node.nodeName === "SCRIPT" && node.type === "text/ng-template") {
$templateCache.put(node.id, node.innerHTML);
}
});
}
Hope this will helps to someone :-)

Related

How to fix template paths in templateCache? (gulp-angular-templatecache)

I'm using gulp-angular-templatecache to generate a templateCache.js file which combines all my HTML template files into 1. (my full gulpfile)
After injecting that new module into my app, my Directives will automatically pick up the templates and I won't need to add the partial .html files into my build folder.
The problem is that the leading folder path is getting cut off, see my example below:
The paths in my Directives:
templateUrl : "panels/tags/tagsPanel.html"...
templateUrl : "header/platform_header/platformHeader.html"...
The paths in my produced templateCache file:
$templateCache.put("tags/tagsPanel.html"...
$templateCache.put("platform_header/platformHeader.html"...
^ panels and header are getting lost.
I'm trying to write a function that will fix that in my Gulpfile.
The config section of my Gulpfile:
var config = {
srcPartials:[
'app/beta/*.html',
'app/header/**/*.html',
'app/help/*.html',
'app/login/*.html',
'app/notificaitons/*.html',
'app/panels/**/*.html',
'app/popovers/**/*.html',
'app/popovers/*.html',
'app/user/*.html',
'app/dashboard.html'
],
srcPaths:[
'beta/',
'header/',
'help/',
'login/',
'notificaitons/',
'panels/',
'popovers/',
'popovers/',
'user/',
'dashboard.html'
],
destPartials: 'app/templates/'
};
My html-templates gulp.task
gulp.task('html-templates', function() {
return gulp.src(config.srcPartials)
.pipe(templateCache('templateCache.js', {
root: updateRoot(config.srcPaths)
},
{ module:'templateCache', standalone:true })
).pipe(gulp.dest(config.destPartials));
});
function updateRoot(paths) {
for (var i = 0; i < paths.length; i++) {
// console.log(paths);
console.log(paths[i]);
return paths[i];
}
}
^ The above is working, in that it uses the root option in gulp-angular-templatecache to append a new string in front of the template paths.
Problem is my code above returns once and updates all the paths to the first item in the paths Array which is beta/.
How would you write this so that it correctly replaces the path for each file?
Figured it out! I should not have been using exact folder names, but globs ** in my config
var config = {
srcTemplates:[
'app/**/*.html',
'app/dashboard.html',
'!app/index.html'
],
destPartials: 'app/templates/'
};
The updated gulp.task:
gulp.task('html-templates', function() {
return gulp.src(config.srcTemplates)
.pipe(templateCache('templateCache.js', { module:'templateCache', standalone:true })
).pipe(gulp.dest(config.destPartials));
});
Now the output is correct:
$templateCache.put("beta/beta.html"...
$templateCache.put("header/control_header/controlHeader.html"...
$templateCache.put("panels/tags/tagsPanel.html"...
I ran into a similar issue, but in my case, it wasn't possible to use the same directory for all the gulp.src entries.
There is a solution that will work all those folders
return gulp.src(['public/assets/app1/**/*.tpl.html', 'public/assets/common_app/**/*.tpl.html'])
.pipe(templateCache({
root: "/",
base: __dirname + "/public",
module: "App",
filename: "templates.js"
}))
.pipe(gulp.dest('public/assets/templates'))
That presumes the gulpfile is one directory up from the public directory. It will remove the base string from the full path of the files from src.
Base can also be a function that will be passed the file object which could be helpful in more complicated situations. It's all around line 60 of the index.js in gulp-angular-templatecache
You can also use this gulp plugin which can read your routes, directives and replace the templateUrl with the template referenced in the templateUrl.
This will remove all headache regarding handling templateUrl in your application. This uses relative url to directive js files instead of absolute url.
src
+-hello-world
|-hello-world-directive.js
+-hello-world-template.html
hello-world-directive.js:
angular.module('test').directive('helloWorld', function () {
return {
restrict: 'E',
// relative path to template
templateUrl: 'hello-world-template.html'
};
});
hello-world-template.html:
<strong>
Hello world!
</strong>
gulpfile.js:
var gulp = require('gulp');
var embedTemplates = require('gulp-angular-embed-templates');
gulp.task('js:build', function () {
gulp.src('src/scripts/**/*.js')
.pipe(embedTemplates())
.pipe(gulp.dest('./dist'));
});
gulp-angular-embed-templates will generate the following file:
angular.module('test').directive('helloWorld', function () {
return {
restrict: 'E',
template:'<strong>Hello world!</strong>'
};
});

AngularJS Translate Static Files Loader

I just recently started learning angular and i'm a bit lost with this code, could some one help me with this. Like, how i can modify it to use my en_US.json which is located at locale/locale-en_US.json.
.factory("$translateStaticFilesLoader", ["$q", "$http",
function(a, b) {
return function(c) {
if (!c || !angular.isString(c.prefix) || !angular.isString(c.suffix)) throw new Error("Couldn't load static files, no prefix or suffix specified!");
var d = a.defer();
return b({
url: [c.prefix, c.key, c.suffix].join("../locale/locale-"),
method: "GET",
params: ".json"
}).success(function(a) {
d.resolve(a)
}).error(function() {
d.reject(c.key)
}), d.promise
}
$translateProvider.preferredLanguage('en_US');
}
]);
I'm feeling a little dumb. I managed to fix my code and the solution was >
app.js(main)
app.config(['$translateProvider', function ($translateProvider) {
$translateProvider.preferredLanguage('en_US');
$translateProvider.useStaticFilesLoader({
prefix: '../locale/locale-',
suffix: '.json'
});
}]);
services.js
app.factory("$translateStaticFilesLoader", ["$q", "$http",
function(a, b) {
return function(c) {
if (!c || !angular.isString(c.prefix) || !angular.isString(c.suffix)) throw new Error("Couldn't load static files, no prefix or suffix specified!");
var d = a.defer();
return b({
url: [c.prefix, c.key, c.suffix].join(""),
method: "GET",
params: ""
}).success(function(a) {
d.resolve(a);
}).error(function() {
d.reject(c.key);
}), d.promise;
}
$translateProvider.preferredLanguage('');
}]);
I just needed to copy the static translate from the original source and paste it to my services and leave all the parameters empty.
Static file loading with $translate is handled by an additional external *.js file that you need to load in. This contains the $translateStaticFilesLoader factory mentioned here.
You can manually copy in the factory like #ALoppu did, but a better approach is to actually load the external script right after angular-translate.js:
<script src="vendor/angular/angular-translate.min.js"></script>
<script src="vendor/angular/angular-translate-loader-static-files.min.js"></script>
You can get the latest copy of angular-translate-loader-static-files.min.js on GitHub here.

How to load multiple JSON files into Jade templates using Grunt?

I can successfully load one JSON file as a data source for my Jade templates using Grunt, similar to this solution.
Now I need to load a set of JSON files from different folders inside my project so that all the data from them is accessible from Jade templates. How to do it better in context of Grunt tasks?
You can load as many json files as you like with this method:
// Jade => HTML
gruntConfig.jade = {
compile: {
options: {
data: {
object: grunt.file.readJSON('JSON_FILE.json'),
object1: grunt.file.readJSON('JSON_FILE_1.json'),
object2: grunt.file.readJSON('JSON_FILE_2.json'),
}
},
}
};
And then in the Jade template you simply need to reference the object. IE:
script(src= object.baseURL + "js/vendor/jquery.js")
script(src= object.baseURL + "js/vendor/elementQuery.js")
script(data-main="js/main", src= object.baseURL + "js/vendor/require.js")
I know this is being answered a bit late but for anyone who comes across this from a google search as I have, this is the answer to loading multiple JSON files into a Jade template using Grunt.js.
You need to combine the Objects before you serve them to Jade. For this I would recommend to use Underscore.js.
Personally I would write a method to fetch the data from the files, like this:
module.exports = function(grunt) {
function combineJSONFiles() {
var object = {};
for(var i=0; i<arguments.length; ++i) {
_(object).extend(grunt.file.readJSON(arguments[i]));
}
return object;
}
grunt.loadNpmTasks('grunt-contrib-jade');
grunt.initConfig(
{
jade: {
html: {
src: './*.jade',
dest: './index2.html',
options: {
client: false,
pretty: true,
data: combineJSONFiles(
"1.json",
"2.json",
"3.json"
)
}
}
}
});
grunt.registerTask('default', 'jade');
};
Hope that helps!

Loading external file from Karma/Jasmine test

I'm trying to accomplish a Jasmine test (using Karma and IntelliJ 13) to validate JSON files. Ideally, my test would simply load a JSON file into a data object, then let me parse through to check for valid formatting and data. I don't need to validate functions before or after, nor do I need to test against a server.
My basic setup is like this:
it("should load an external file", function(){
var asyncCallComplete, result,
_this = this;
// asyncCallComplete is set to true when the ajax call is complete
asyncCallComplete = false;
// result stores the result of the successful ajax call
result = null;
// SECTION 1 - call asynchronous function
runs(function() {
return $.ajax('/test/config.json', {
type: 'GET',
success: function(data) {
asyncCallComplete = true;
result = data;
},
error: function() {
asyncCallComplete = true;
}
});
});
// SECTION 2 - wait for the asynchronous call to complete
waitsFor(function() {
return asyncCallComplete !== false;
}, "async to complete");
// SECTION 3 - perform tests
return runs(function() {
return expect(result).not.toBeNull();
});
}
The problem is that no matter what path I use, I get a 404 error and the file won't load. I've tried loading an external JSON result from a remote server using this test service:
http://date.jsontest.com/
And this works.
My test file is named /test/mySpec.js and my karma.conf.js file is on the root. I have moved around the JSON file to all of these locations with no luck. What am I doing wrong?
UPDATE WITH ANSWER:
Per the answer below, I added this to my karma.conf.js:
// fixtures
{ pattern: 'test/*.json',
watched: true,
served: true,
included: false
}
Then, I wrote my test this way:
var json:any;
it("should load a fixture", function () {
jasmine.getFixtures().fixturesPath = "base/test/"
var f = readFixtures("registration.json");
json = JSON.parse(f);
expect(json).toBeDefined();
})
it("should have a title", function () {
expect(json.title).toNotBe(null);
})
etc...
And it passes.
Are you serving the JSON file via karma.config.js?
You can serve JSON files via fixture:
files: [
// angular
'angular.min.js',
'angular-route.js',
'angular-mocks.js',
// jasmine jquery helper
'jquery-1.10.2.min.js',
'jasmine-jquery.js',
// app
'../../public/js/app.js',
// tests
'*-spec.js',
// JSON fixture
{ pattern: '/test/*.json',
watched: true,
served: true,
included: false }
],
Serving JSON via the fixture is the easiest but because of our setup we couldn't do that easily so I wrote an alternative helper function:
Install
bower install karma-read-json
Usage
Put karma-read-json.js in your Karma files, Example:
files = [
...
'bower_components/karma-read-json/karma-read-json.js',
...
]
Make sure your JSON is being served by Karma, Example:
files = [
...
{pattern: 'json/**/*.json', included: false},
...
]
Use the readJSON function in your tests. Example:
var valid_respond = readJSON('json/foobar.json');
$httpBackend.whenGET(/.*/).respond(valid_respond);
If you are trying to load a HTML file and want to avoid using jasmine-jquery, you may take advantage of the karma-ng-html2js-preprocessor.
In your karma.conf.js :
// generate js files from html templates
preprocessors: {
'resources/*.html': 'ng-html2js'
},
files: [
...
'resources/*.html'
],
plugins: [
...
'karma-ng-html2js-preprocessor'
],
In your jasmine spec :
beforeEach(module('resources/fragment.html'));
var $templateCache;
beforeEach(inject(function (_$templateCache_) {
$templateCache = _$templateCache_;
}));
describe('some test', function () {
it('should do something', function () {
// --> load the fragment.html content from the template cache <--
var fragment = $templateCache.get('resources/fragment.html');
expect(fragment).toBe(...);
});
});
Have you tried simply requiring the json file and storing it as a global variable in your test?
I'm developing an Angular2 project right now (using the Angular CLI), and with this setup it works:
// On the very beginning of the file
let mockConfig = require('./test/config.json');

How to use relative paths in require.config?

I'd like to distribute a piece of code as an AMD module. The module depends on jQuery in a noConflict mode with two jQuery plugins.
I'd like the user to be able to use the module by simply requiring a single module file (module will be hosted on our servers), and let the dependencies be handled for them. However, for the dependencies to be loaded properly, I have to invoke require.config() and it seems to have the module paths relative to the web page, not to the invoking script. I could use the paths configuration to make all the paths absolute. That would solve the dependency problem, but would also make testing anywhere outside our production server a nightmare.
To be more specific, the module file looks roughly like this:
define (['./jquery-wrapper'], function ($) {
...
return module;
});
And the jquery-wrapper.js file in the same directory looks like this:
require.config ({
paths: {
'jquery-original': '//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min',
// ^ naturally, this one has to be absolute
},
shim: {
'jquery-original': {
exports: '$',
},
'../plugin/js/jquery.nouislider.min': {
// ^ this path is relative to the web page, not to the module
deps: ['jquery-original'],
},
'../plugin/js/jquery.ie.cors': {
// ^ this path is relative to the web page, not to the module
deps: ['jquery-original'],
},
},
});
define (['jquery-original', './jquery.nouislider.min', './jquery.ie.cors'], function ($, slider, cors) {
// ^ these paths are relative to the module
console.log ('types: ' + typeof slider + typeof $.noUiSlider + typeof cors);
return $.noConflict (true);
});
Is there any way I can use paths relative to the module everywhere?
I think you can use separate configs to get this to work:
file structure
The other/module path simulates the other server in this example.
¦ a.js
¦ b.js
¦ c.js
¦ test.html
¦
+---other
+---module
main.js
module-file-1.js
other/module/main.js
Has a dependency, using a relative module name.
define(["./module-file-1"], function (mf1) {
console.log("load main", "deps", mf1);
return "main";
});
a.js
Has a dependency, using a relative module name.
define(["./b"], function(b) {
console.log("load a", "deps", b);
return "a";
});
b.js and c.js
Uninteresting.
define(function () {
console.log("load b");
return "b";
});
other/module/module-file-1.js
Uninteresting.
define(function () {
console.log("load module-file-1");
return "module-file-1";
});
test.html
Set up two require contexts, use each to load their own modules, and then wait for both sets of modules to load:
<script src="http://requirejs.org/docs/release/2.1.8/comments/require.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
var localRequire = require({
context: "local"
});
var moduleRequire = require({
context: "module",
baseUrl: "http://localhost/other/module/"
});
function deferredRequire(require, deps) {
return $.Deferred(function(dfd) {
require(deps, function() {
dfd.resolve.apply(dfd, arguments);
});
}).promise();
}
$.when(deferredRequire(moduleRequire, ["main"]), deferredRequire(localRequire, ["a", "b", "c"])).then(function(deps1, deps2) {
// deps1 isn't an array as there's only one dependency
var main = deps1;
var a = deps2[0];
var b = deps2[1];
var c = deps2[2];
console.log("Finished", main, a, b, c);
});
</script>
Console
load b
load a deps b
load c
load module-file-1
load main deps module-file-1
Finished main a b c

Categories

Resources