I have an Angular, Node based app. It uses Jade for templating. I want to hide or show chunks of my page depending on the NODE_ENV variable that I use to start node with.
Something like this (not sure about how to check "else not" with ng-if):
div(ng-if="testingmode")
{{somescopevar}}
div(ng-if != "testingmode")
{{differentscopevar}}
The kicker is that testingmode is determined by what the NODE_ENV variable is. I can access that variable within my jade templates but don't know how to get it into my Angular scope.
tl;dr: How do I get NODE_ENV into my Angular scope?
Personally I would create an api call that returns that value, and then have angular grab it in a controller using $http.
In your node routes:
app.get('/nodeenv', function(req, res, next){
return res.json({ env: app.get('env') });
});
In your angular controller:
$http.get('/nodeenv').success(function(data){
$scope.myEnvironment = data.env;
});
UPDATE:
A new way I have been doing this with newer projects is generating my root index file as a template in node (eg. with doT templates). Then passing any constants into the template to be loaded directly into angular. Below is the way you could pass in the environment for example:
index.def
<html>
<head><!-- head stuff --></head>
<body>
<div>scripts and content go here</div>
<!-- initialise any templated constants -->
<script>
angular.module('mymodule').constant('globals', {
env: '{{=it.env}}'
});
</script>
</body>
</html>
As an alternative you could put this in your build system with gulp-replace. I'm sure grunt has a similar feature.
index.html
<script>
var ENV = 'NODE_ENV'; // replaced by gulp
</script>
gulpfile.js
gulp.task('setEnv', function(){
gulp.src(['index.html'])
.pipe(replace(/NODE_ENV/g, process.env.NODE_ENV))
.pipe(gulp.dest('build/index.html'));
});
Haven't test the exact code, but you get the gist.
Related
I use brunch for compilation of static assets. I've an index.html containing a <script> tag with environment variable placeholders. Based on the environment I want to change the placeholders to actual values. How can I do it the simplest way using brunch?
I tried several plugins, but although sounds to be a simple task, I fail to get anything replaced.
You can install handlebars-brunch plugin from master, add
handlebars: {
locals: {
env: process.env
}
}
to plugins in brunch-config.js, rename index.html to index.html.hbs and use it like this:
<script>
alert("{{env.key}}")
</script>
I'm working on an existing (and working) Angular 1.5.5 app. It's very small and has a controller, a directive and a couple of services, all split into individual files.
I'd now like to move to Webpack and make the minimum number of changes to the app to support that. A lot of the Webpack/Angular demos I've found have been about creating a new Angular app with web pack built in from the start, but I don't want to rebuild the existing app, just make whatever changes are necessary to use a webpack-produced bundle. It's also using regular JS, whereas most of the tutorials I've seen are for ES6.
I've got grunt-webpack installed and working, it's creating the bundle.js file and I can see inside the bundle that it's pulling in Angular, Angular-aria and Angular-animate (my module dependencies)
However, when I run the site I see an error:
Uncaught TypeError: angular.module is not a function
My webpack task is as follows:
module.exports = {
dist: {
entry: './Static/js/Ng/app.js',
output: {
path: './Static/dist/js',
filename: 'bundle.js'
}
}
};
As I say, the actual Webpack bundling seems to be working as expected and creates the bundle.js file.
The main entry file (app.js) is as follows:
(function () {
'use strict';
var angular = require('../vendor/angular.js');
var ngAria = require('../vendor/angular-aria.js');
var ngAnimate = require('../vendor/angular-animate.js');
angular.module('app', [ngAria, ngAnimate]);
}());
If I log out the angular variable in this file, it's just an empty object, even though I can see the Angular source in the bundle.
What am I missing?
You probably shadow the global angular property by your local var angular variable. Try this:
(function () {
'use strict';
require('../vendor/angular.js');
require('../vendor/angular-aria.js');
require('../vendor/angular-animate.js');
angular.module('app', [ngAria, ngAnimate]);
}());
Good day,
I've tried using both ng-html2js and grunt-html2js to try to load my directive templates as modules when testing but have hit a-bit of a road block on both cases. My questions will revolve around the former as this is what I've attempting to use most.
Correct me if I'm wrong; In order to use ng-html2js you must first register the module from node like so:
npm install karma-ng-html2js-preprocessor -g
This installs it globally which is what I want as I run my karma
tests using the following command which hands over to the global instance of karma installed.:
karma start
Next in the karma.conf.js file you must then specify which templates you
want to use and what dependency it is to be used with:
preprocessors: {
'webapp/scripts/*.js': 'coverage',
'webapp/modules/**/*.js': 'coverage',
'webapp/modules/groupbydrug.html': 'ng-html2js'
},
When it comes to the test, we can load the module doing this:
beforeEach(module('webapp/modules/groupbydrug.html'));
Finally we compile as usual, add the directive to a piece of html and test:
beforeEach(function () {
ele = angular.element('<div group-by-drug=""></div>');
compile(ele)(scope);
scope.$digest();
});
it('should have a table with a class of "drugs-by-mail"', function () {
var div = ele.find('div.outrepeat');
console.log(div);
});
BTW - The template looks like this:
<div ng-repeat="(orderNumber,orderData) in orders" class="drugs-by-mail">
<table class="recent-order-mail">
...
</table>
</div>
Based on what I've read I should beable to retrieve the div from the template but when I try and print it to the console I get an empty object (Object{}) when I'd actually expect to see all the content within that div - is that not correct?
So where along here am I going wrong? Or is this an issue with installation (global karma vs local)
Thanks
I'm using gulp-angular-templatecache, to grab all my partial HTML template files and combined them into 1 template.js file.
The first part I was able to complete, I can run my Gulp task and it creates templates/templates.js.
templates.js:
angular.module("templates").run(["$templateCache", function($templateCache) {$templateCache.put("beta.html","<div class=\"login-container\" ng-controller=\"BetaCtrl as beta\">\n <section class=\"login-form-block\">\n <header>\n <div class=\"tickertags-logo-big\"></div>\n <h1>Welcome to the TickerTags beta! Enter the email address where your beta invitation was sent below. We will send you an email with your temporary password.</h1>\n </header>\n\n <div class=\"login-form\">\n\n <form name=\"loginForm\" ng-submit=\"beta.beta(credentials)\" novalidate>\n\n <div class=\"login-alert\" ng-class=\"{ hideLoginMsg: beta.hideMessage == true }\">{{ beta.message }}</div>\n\n <input type=\"email\"\n id=\"email\"\n placeholder=\"Email\"\n name=\"email\"\n ng-model=\"credentials.email\">\n\n <button type=\"submit\" class=\"login-btn\">Email Password</button>\n </form>\n\n <p class=\"terms-of-use-line\">By signing up you agree to our Terms of Use and Privacy Policy</p>\n\n </div>\n </section>\n</div>\n");
Now I've linked to the templates.js file correctly in my index:
<script src="templates/templates.js"></script> <<--
<script src="authentication/authFactory.js"></script>
<script src="help/helpController.js"></script>
etc...
And I've included it in the main app module:
var app = angular.module('tickertags', [
'ui.router',
'templates', // <--
'authFactory',
'betaController',
'passResetController',
'loginController',
'apiFactory',
'scopeFactory',
etc...
Yet getting this error still:
https://docs.angularjs.org/error/$injector/nomod?p0=templates
Error: $injector:nomod
Module Unavailable
Ideas on why I'm seeing that?
Because that module wasn't declared properly.
You need to declare the templates module somewhere in your app like this: angular.module("templates", []); Or use options.standalone = true in the gulp plugin
From the documentation:
Note: this plugin will not create a new AngularJS module by default, but use a module called templates. If you would like to create a new module, set options.standalone to true.
What is a good approach to pass setting to AngularJS app?
Technology stack:
Node.js
AngularJS
Settings look like this:
window.settings = {};
settings.webSocketURL = 'ws://domain.com/websocket';
settings.webSocketTopic = 'name';
Here are few options:
Include script
<script src="scripts/settings.js"></script>
Disadvantages: settings.js file is in scripts directory and not the root directory, additional script to load.
Include script like in 1 but settings.js is generated by Node.js.
Disadvantage: additional script to load.
Embed setting directly into HTML.
Disadvantage: need to use templating like EJS instead of HTML.
I had a similar problem, and I solved using the config:
myapp
.constant("settings", {
"webSocketURL": 'ws://domain.com/websocket',
"webSocketTopic": "name"
})
then in your controllers you just have to inject the settings, and get them for example with settings.webSocketURL
I suppose you could create a config module anywhere you want
// config/app.coffee
angular.module('MyAppConfig', [])
.config ($provide) ->
$provide.constant 'webSocketURL', 'ws://domain.com/websocket'
$provide.constant 'webSocketTopic', 'name'
And use a Grunt task, or script or whatever to concatenate it with your application script.
Here is my solution:
Put client settings in server config.
config.settings = {};
Generate JS file with Node.js
app.get('/settings.js', function(req, res) {
res.setHeader('Content-Type', 'application/javascript');
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
res.setHeader('Pragma', 'no-cache');
res.setHeader('Expires', 0);
res.send('window.settings = ' + JSON.stringify(config.settings) + ';');
});
Define AngularJS constant
ngular.module('app')
.constant('settings', window.settings)