AngularJS app initializes but doesn't work - angularjs

I have started a pet project with AngularJS and Gulp. The code is available on github.
After building the project my dist folder looks like this:
js/
--vendor.js
--app.js
index.html
When I run browserSync in dist folder, everything seems to work fine: the paths are injected correctly, angular global variable is available in chrome console, and ng-app directive is on its place. However, if I try to create a controller or config an app, the scripts inside the functions don't run.
That's the first time when I actually wrote gulpfile.js entirely by myself, based on various tutorials. I suspect that the problem may be in improper gulp configuration, but I'm not sure.

in index.html change ng-app to ng-app="app" add browser-sync in dependencies. other than that everything is fine.

Firstly, you need to specify module name in ngApp directive. This will fix problem that config and run blocks are not running.
Also you have to add ngController directive somewhere. For example on body html tag.
Result:
Example of final html code:
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<meta charset="UTF-8">
<title>FinControl</title>
<!-- build:css css/vendor.css -->
<!-- bower:css -->
<!-- endbower -->
<!-- endbuild -->
<!-- build:css css/main.css -->
<!-- inject:css -->
<!-- endinject -->
<!-- endbuild -->
</head>
<body ng-controller="testCtrl" layout="column" layout-fill>
<input type="text" ng-model="textVal">
<span>{{textval}}</span>
</body>
<!-- build:js js/vendor.js -->
<!-- bower:js -->
<!-- endbower -->
<!-- endbuild -->
<!-- build:js js/app.js -->
<!-- inject:js -->
<!-- endinject -->
<!-- endbuild -->
</html>

Related

Angular ui-select breaks after minifying

I currently need to maintain an angular.js 1.5 application which uses angular-ui-select 0.19.8.
The problem I'm having is, that the ui-select somehow breaks when packaging the app.
When running with grunt serve, this part:
<ui-select mandatory-field-marker
multiple ng-required="true"
ng-model="some.periods">
<ui-select-match placeholder="Select some periods...">
{{$item | period}}
</ui-select-match>
<ui-select-choices
repeat="period in formCtrl.periods">
<div ng-bind-html="period | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
results in this output:
When running the packaged app, it looks like this:
It's not just a style problem, the broken input field doesn't allow more than 10 elements before it becomes unclickable due to shifting into the next component.
The packaging is done with grunt and as far as I can see, those are the steps used to minify the code:
useminPrepare
concat
ngAnnotate
imagemin
autoprefixer
cssmin
usemin
htmlmin
I've found some workarounds, like downgrading ui-select and adding matching classes to <ui-select> and <ui-select-choices> but none of them worked.
The ui-select dependency pulled by bower seems to be minified already:
Update: This seems to be a problem with grunt and/or bower.
After reconfiguring the Apache hosting the website, I've reached the error, that the vendor.min.css is missing.
I've found the part in the (generated by bower) index.html head where it says:
<!-- build:css(.) styles/vendor.min.css -->
<!-- bower:css -->
<link rel="stylesheet" href="bower_components/angular-ui-select/dist/select.css" />
<link rel="stylesheet" href="bower_components/ng-tags-input/ng-tags-input.css" />
<!-- endbower -->
<!-- endbuild -->
<!-- build:css(.) styles/bootstrap.min.css -->
<link rel="stylesheet" href="styles/bootstrap.css">
<!-- endbuild -->
<!-- build:css(.) styles/main.min.css -->
<link rel="stylesheet" href="styles/main.css">
<!-- endbuild -->
however, only the bootstrap.min.css and main.min.css are packaged into my dist:
Still don't know the reason.
I've fixed it but not very elegantly.
The problem was, that the select.css and ng-tags-input.css where not packaged into a vendor.min.css, so they where missing after deployment.
I could not identify which grunt-task should build the vendor.min.css, but at least I know that whoever should do it, didnt'.
So in the index.html I've changed the part
<!-- build:css(.) styles/vendor.min.css -->
<!-- bower:css -->
<link rel="stylesheet" href="bower_components/angular-ui-select/dist/select.css" />
<link rel="stylesheet" href="bower_components/ng-tags-input/ng-tags-input.css" />
<!-- endbower -->
<!-- endbuild -->
<!-- build:css(.) styles/bootstrap.min.css -->
<link rel="stylesheet" href="styles/bootstrap.css">
<!-- endbuild -->
<!-- build:css(.) styles/main.min.css -->
<link rel="stylesheet" href="styles/main.css">
<!-- endbuild -->
to
<!-- build:css(.) styles/select.min.css -->
<link rel="stylesheet" href="bower_components/angular-ui-select/dist/select.css" />
<!-- endbuild -->
<!-- build:css(.) styles/ng-tags-input.min.css -->
<link rel="stylesheet" href="bower_components/ng-tags-input/ng-tags-input.css" />
<!-- endbuild -->
<!-- build:css(.) styles/bootstrap.min.css -->
<link rel="stylesheet" href="styles/bootstrap.css">
<!-- endbuild -->
<!-- build:css(.) styles/main.min.css -->
<link rel="stylesheet" href="styles/main.css">
<!-- endbuild -->
which now works.
This will be a problem, if there are any more css-files from bower_components in the future, but the application I'm talking about is going to be put out of service next year, so it doesn't matter.

How to incorporate ES6 transpiler into Angular gulp build process

In order to prepare my app for production I use the below gulp task. The task is quiet self explanatory, all .js files are uglified and placed into build folder
var jsLibFilter = $.filter('**/lib.js');
var jsAppFilter = $.filter('**/app.js');
var buildPath = './build/';
gulp.task('build', function() {
return gulp.src(config.index)
<!-- pick up all files in index which are under "lib.js" tag -->
.pipe(jsLibFilter)
.pipe($.uglify())
.pipe(jsLibFilter.restore())
<!-- pick up all files in index which are under "app.js" tag -->
.pipe(jsAppFilter)
.pipe($.ngAnnotate())
.pipe($.uglify())
.pipe(jsAppFilter.restore())
.pipe(gulp.dest(buildPath));
});
There is a whole bunch of other things that happen within the upper task which I have not included for sake of clarity.
A small snapshot of index.html below:
<body>
<!-- build:js js/lib.js -->
<!-- bower:js -->
<script src="/bower_components/jquery/dist/jquery.js"></script>
<script src="/bower_components/angular/angular.js"></script>
...other libraries here
<!-- endbower -->
<!-- endbuild -->
<!-- build:js js/app.js -->
<!-- inject:js -->
<script src="/client/app/app.module.js"></script>
<script src="/client/app/history/historyController.js"></script>
..other source code files here
<!-- endinject -->
<!-- endbuild -->
</body>
I have two specific questions:
How to incorporate ES6 during development. e.g. how do I apply babel transpiler while developing.
Do keep in mind that during development I am serving files from the "/app" folder
How to incorporate ES6 during production
During production the files are served from build folder for which I have provided the build task above.

One specific file missing from injected bower_components

I just installed Angular UI Grid via Bower.
My bower_components directory looks like this:
.
..
angular
angular-animate
angular-cookie
angular-cookies
angular-mocks
angular-resource
angular-sanitize
angular-touch
angular-ui-grid <-- the interesting directory
angular-ui-router
angularjs-rails-resource
bootstrap-sass-official
fontawesome
jquery
ng-token-auth
Confusingly, my index file looks like this:
<!-- build:js(src) scripts/vendor.js -->
<!-- bower:js -->
<script src="../bower_components/jquery/dist/jquery.js"></script>
<script src="../bower_components/angular/angular.js"></script>
<script src="../bower_components/angular-animate/angular-animate.js"></script>
<script src="../bower_components/angular-cookies/angular-cookies.js"></script>
<script src="../bower_components/angular-touch/angular-touch.js"></script>
<script src="../bower_components/angular-sanitize/angular-sanitize.js"></script>
<script src="../bower_components/angular-resource/angular-resource.js"></script>
<script src="../bower_components/angular-ui-router/release/angular-ui-router.js"></script>
<script src="../bower_components/bootstrap-sass-official/assets/javascripts/bootstrap.js"></script>
<script src="../bower_components/angular-cookie/angular-cookie.js"></script>
<script src="../bower_components/ng-token-auth/dist/ng-token-auth.js"></script>
<script src="../bower_components/angularjs-rails-resource/angularjs-rails-resource.js"></script>
<!-- endbower -->
<!-- endbuild -->
Notice the absence of angular-ui-grid.
It's not that there are no .js files in bower_components/angular-ui-grid:
$ find bower_components/angular-ui-grid -name '*.js'
bower_components/angular-ui-grid/ui-grid.js
bower_components/angular-ui-grid/ui-grid.min.js
What could be the problem?
Ah ha. I had angular-ui-grid in devDependencies in bower.json. It needed to be in dependencies.

yeoman based angular app integration with laravel API in one domain

I'm working on AngularJS single page app which is designed to hit API endpoint writing in laravel 5. The API developed by other team. The project run smooth until the design change (by client request). They want to put the Angular app in the same domain with Laravel. I've found many articles to help me integrate angular with laravel. The most visible solution I found is user Alias comment in laracast.
I developed the angular app with Yeoman gulp-angular generator (it does scaffolding, minify, and serve the app on browser. so I can focus on writing app instead of importing dependencies files and refreshing browser ).
Now the app already 80% complete, i have to integrate my dev folder with laravel. In other word i have to develop the rest of the app inside laravel realm. I don't want to get rid the yeoman gulp-angular generator from my workflow because it's really helpful. But in the other hand i need to make laravel serve my app when i hit a url (for example : laravelapp/my/app).
So i did the following things (based on user alias comment on laracast):
I put my dev folder inside laravel public/myapp folder
I create a laravel route to return a my app view.
I create a laravel view that should serve my app.
But how can I call my app from the laravel view? The app already have its own index.html file (provided by yeoman gulp-angular generator) and it's already contain its own angular ui-view element, and some cryptic code to inject my app dependencies out of the box. any advice guys? Thank you.
My directory structure:
LaravelAPI
|
---- Resources
| |----------views
| |--------MyApp.php // laravel view for myapp
|
|----Public
|----------index.php
|----------pos // this is my app
|------bower_components, gulp, etc // generated by yeoman
|------ ....
|------src // my src
|----- index.html // this file is what i want to be called from laravel view
|------ dist // minified/production version of my app
My Laravel view (MyApp.php)
The following is the laravel view i created by copy and paste index.html from myapp. The index html i pasted here is the after compiled version of yeoman gulp-angular generator. My application name is pos, so i prefixed all dependencies with it.
<!doctype html>
<html class="no-js">
<head>
<meta charset="utf-8">
<title>fortunixPos</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
<!-- build:css({.tmp/serve,src}) styles/vendor.css -->
<!-- bower:css -->
<link rel="stylesheet" href="pos/bower_components/angular-material/angular-material.css" />
<!-- endbower -->
<!-- endbuild -->
<!-- build:css({.tmp/serve,src}) styles/app.css -->
<!-- inject:css -->
<link rel="stylesheet" href="pos/src/app/index.css">
<!-- endinject -->
<!-- endbuild -->
</head>
<body><script type='text/javascript' id="__bs_script__">//<![CDATA[
// document.write("<script async src='/browser-sync/browser-sync-client.1.7.3.js'><\/script>".replace(/HOST/g, location.hostname).replace(/PORT/g, location.port));
//]]></script>
<!--[if lt IE 10]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please upgrade your browser to improve your experience.</p>
<![endif]-->
<div ui-view></div>
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
<script>
// (function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
// function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
// e=o.createElement(i);r=o.getElementsByTagName(i)[0];
// e.src='//www.google-analytics.com/analytics.js';
// r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
// ga('create','UA-XXXXX-X');ga('send','pageview');
</script>
<!-- build:js(src) scripts/vendor.js -->
<!-- bower:js -->
<script src="pos/bower_components/jquery/dist/jquery.js"></script>
<script src="pos/bower_components/angular/angular.js"></script>
<script src="pos/bower_components/angular-animate/angular-animate.js"></script>
<script src="pos/bower_components/angular-cookies/angular-cookies.js"></script>
<script src="pos/bower_components/angular-touch/angular-touch.js"></script>
<script src="pos/bower_components/angular-sanitize/angular-sanitize.js"></script>
<script src="pos/bower_components/lodash/dist/lodash.compat.js"></script>
<script src="pos/bower_components/restangular/dist/restangular.js"></script>
<script src="pos/bower_components/angular-ui-router/release/angular-ui-router.js"></script>
<script src="pos/bower_components/angular-aria/angular-aria.js"></script>
<script src="pos/bower_components/hammerjs/hammer.js"></script>
<script src="pos/bower_components/angular-material/angular-material.js"></script>
<script src="pos/bower_components/angular-utils-pagination/dirPagination.js"></script>
<!-- endbower -->
<!-- endbuild -->
<!-- build:js({.tmp/serve,.tmp/partials,src}) scripts/app.js -->
<!-- inject:js -->
<script src="pos/src/app/index.js"></script>
<script src="pos/src/components/navbar/navbar.controller.js"></script>
<script src="pos/src/app/pos/terminalSession.js"></script>
<script src="pos/src/app/pos/shoppingCart.js"></script>
<script src="pos/src/app/pos/pos.controller.js"></script>
<script src="pos/src/app/pos/payment.js"></script>
<script src="pos/src/app/pos/itemlist.js"></script>
<script src="pos/src/app/pos/initCash.controller.js"></script>
<script src="pos/src/app/main/main.controller.js"></script>
<!-- endinject -->
<!-- inject:partials -->
<!-- angular templates will be automatically converted in js and inserted here -->
<!-- endinject -->
<!-- endbuild -->
</body>
</html>
And this is the actual HTML from yeoman gulp-angular generator which is do nothing when i put it in laravel view:
<!doctype html>
<html class="no-js">
<head>
<meta charset="utf-8">
<title>fortunixPos</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
<!-- build:css({.tmp/serve,src}) styles/vendor.css -->
<!-- bower:css -->
<!-- run `gulp wiredep` to automaticaly populate bower styles dependencies -->
<!-- endbower -->
<!-- endbuild -->
<!-- build:css({.tmp/serve,src}) styles/app.css -->
<!-- inject:css -->
<!-- css files will be automaticaly insert here -->
<!-- endinject -->
<!-- endbuild -->
</head>
<body>
<!--[if lt IE 10]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please upgrade your browser to improve your experience.</p>
<![endif]-->
<div ui-view></div>
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
<script>
// (function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
// function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
// e=o.createElement(i);r=o.getElementsByTagName(i)[0];
// e.src='//www.google-analytics.com/analytics.js';
// r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
// ga('create','UA-XXXXX-X');ga('send','pageview');
</script>
<!-- build:js(src) scripts/vendor.js -->
<!-- bower:js -->
<!-- run `gulp wiredep` to automaticaly populate bower script dependencies -->
<!-- endbower -->
<!-- endbuild -->
<!-- build:js({.tmp/serve,.tmp/partials,src}) scripts/app.js -->
<!-- inject:js -->
<!-- js files will be automaticaly insert here -->
<!-- endinject -->
<!-- inject:partials -->
<!-- angular templates will be automatically converted in js and inserted here -->
<!-- endinject -->
<!-- endbuild -->
</body>
</html>
This might be late a little bit. Put all of your resources (*.html) generated by yeoman in laravel partial views. Create the angular routes like following then put your partial in custom template. It worked for me.
myPartial.blade.php
<h1>Home</h1>
<h3>{{message}}</h3>
your angular route file:
var app = angular.module('myApp', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl : 'pages/home.html',
controller : 'HomeController'
})
});
your app.blade.php :
<body>
<script type="text/ng-template" id="pages/home.html">
#include('myPartial')
</script>
Home
</body>

Bower with Bootstrap 3

Trying out Yeoman (1.0.4). Generated an Angular app with yo angular; entered No to installing Bootstrap with Sass, as I wanted Bootstrap v 3 with LESS.
After scaffolding, to get Bootstrap 3, I entered:
bower install bootstrap
That installed bootstrap into bower_components/bootstrap folder. But it did not link/include Bootstrap's CSS or JS in index.html file. Why?
The index.html file does have Angular js files from bower_components folder:
<!-- build:js scripts/modules.js -->
<script src="bower_components/angular-resource/angular-resource.js"></script>
<script src="bower_components/angular-cookies/angular-cookies.js"></script>
<script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<!-- endbuild -->
But not bootstrap files. Why? Do I have to add/link to them manually? What am I doing wrong? How can I add Bootstrap after generating a scaffold for my app?
According to yeoman's Getting Started guide:
# Install it and save it to bower.json
>bower install jquery-pjax --save
# If you're not using RequireJS...
>grunt bower-install
This is supposed to inject your dependencies into your index.html file.
Note:
There is some setting up that needs to be done, before being able to use bower-install.
See, here for more details.
You must edit the index.html. Yeoman generator builds the base index.html. Bower only downloads dependencies as packages... but that's all, it doesn't know anything else about your app and how are you going to use the packages it downloaded. You must add the desired files by yourself.
With https://github.com/stephenplusplus/grunt-bower-install, if you have the following in your index.html
<!-- build:js scripts/vendor.js -->
<!-- bower:js -->
<script src="bower_components/jquery/jquery.js"></script>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/sass-bootstrap/dist/js/bootstrap.js"></script>
<script src="bower_components/angular-resource/angular-resource.js"></script>
<script src="bower_components/angular-cookies/angular-cookies.js"></script>
<script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
<!-- endbower -->
<!-- endbuild -->
Then bower install will add the vendor files to your html whenever it runs. Otherwise, yes.
Using yeoman, you install dependencies with the --save flag to update the bower.json file.
After that, you run $ bower update(optional) and do a $ grunt wiredepto inject the dependencies into your index.html.
If you look at the comments in your index.html generated by Yeoman, you will see something like:
<!-- build:js(.) scripts/vendor.js -->
<!-- bower:js -->
<script src="bower_components/modernizr/modernizr.js"></script>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/json3/lib/json3.js"></script>
<script src="bower_components/angular-resource/angular-resource.js"></script>
<script src="bower_components/angular-cookies/angular-cookies.js"></script>
<script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
<script src="bower_components/angular-animate/angular-animate.js"></script>
<script src="bower_components/angular-touch/angular-touch.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
<script src="bower_components/angular-ui-router/release/angular-ui-router.js"></script>
<script src="bower_components/angular-block-ui/dist/angular-block-ui.js"></script>
<!-- endbower -->
<!-- endbuild -->
It is within those comments that the dependencies will be injected
Wiredep does it without depending on Grunt or any other build tool: https://github.com/taptapship/wiredep
npm install --save wiredep
Insert placeholders in your code where your dependencies will be injected:
<html>
<head>
<!-- bower:css -->
<!-- endbower -->
</head>
<body>
<!-- bower:js -->
<!-- endbower -->
</body>
</html>
Let wiredep work its magic:
$ node
> require('wiredep')({ src: 'index.html' });
Since Bootstrap version 3.3.5, the bootstrap.css file has been removed from Bootstrap's package manager json. Thus, I had to roll back to version 3.3.4 before running wiredep.
bower install --save bootstrap#3.3.4

Resources