Project structure for large Angular application? - javascript

I am new to angular js
I want to create my project structure like this
- APPLICATION
-index.html
-app.js
-modules
-core
-controllers
-directive
-views
-core.app.js
-core.config.routes.js
-test
-controllers
-directive
-views
-test.app.js
-test.config.routes.js
Here core, test is different modules(ng-app)
I configure like Here
app.js
angular.module('mainapp',['mainapp.core','mainapp.test'])
core.app.js
angular.module('mainapp.core',[])
test.app.js
angular.module('mainapp.test',[])
Here I am gettiing problem that my core module states are not working properly . I am using $staeprovider(ui-views) for routing.
example
core.config.routes.js
angular.module('mainapp.core').config(function($stateProvider,
$urlRouterProvider) {
$stateProvider
.state('core', {
url: '/core',
templateUrl: 'modules/core/views/core.html',
})
.state('core.sidebar ', {
url: '^/sidebar ',
templateUrl: 'modules/core/views/core.sidebar .html'
})
});
test.config.routes.js
angular.module('mainapp.test').config(function($stateProvider,
$urlRouterProvider) {
$stateProvider
.state('core.sidebar .test', {
url: '^/test',
templateUrl: 'modules/core/views/test.html'
})
});
my html pages are
index.html
<div ng-app="mainapp">
<div ui-view= ""></div>
</div>
core.html
` <div>
<h1>I am designing jeader Here. it goes on tp of page</h1>
<div ui-view></div>
</div>`
core.sidebar .html
`<div>
<h2>It goes left side</h2>
<h1>I am designing sidebar Here</h1>
<div ui-view></div>
</div>`
till Here it's working fine. heaser, sider bar is loading $state at core.sidebar
Here I am getting problem it' not working
test.html
<div>
<h1>I am designing middle content Here</h1>
</div>
Please any one help me to solve the issue and build better approach for project structure

I recommend you look at the Angular Style Guide in how they recommend project structuring. https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md#application-structure-lift-principle
I really like their recommendation for using the LIFT approach:
Locating our code is easy
Identify code at a glance
Flat structure as long as we can
Try to stay DRY (Don’t Repeat Yourself) or T-DRY
In that spirit, you might just have a modules folder and then use a file naming convention to keep things organized. On my projects, I do this and use ng-structure prefixes. Example:
nx.core
controller.header
controller.footer
controller.app
routes
nx.admin
routes
controller.admin
directive.blah
Doing this, I was able to achieve both the flat organization as well as a quickly filtering by eye, what files I need. Then only drawback is if you use a shortcut in your IDE to quickly open files, you normally think in terms of FindingsController not via a prefix like controller.Findings.
Just my 2¢

Related

How does the following `src='${loadingGif}'` work inside angular component

I'm reading the book ng-book on angular 2 and there is the following:
let loadingGif: string = ((<any>window).__karma__) ? '' : require('images/loading.gif');
#Component({
selector: 'youtube-search',
template: `
<div class='container'>
<div class="page-header">
<h1>YouTube Search
<img
style="float: right;"
*ngIf="loading"
src='${loadingGif}' />
</h1>
</div>
I'm interested in this part:
src='${loadingGif}'
The short note in the book says the following:
Notice that our img has a src of ${loadingGif} - that loadingGif
variable came from a require statement earlier in the program. Here
we’re taking advantage of webpack’s image loading feature. If you want
to learn more about how this works, take a look at the webpack config
in the sample code for this chapter or checkout
image-webpack-loader⁴².
But there are no details. Can somebody please how does it all work?
This only works with inline templates (template in *.ts file) but not when the template is in an *.html file (like templateUrl: './my.component.html).
src='${loadingGif}'
Is TypeScript string interpolation and not related to Angular. It replaces ${loadingGif} with the content of loadingGif

AngularJS ui-view displays nothing when running grunt serve:dist

I've been trying to make this code that I inherited work for a couple of days now but I still got no luck. Admittedly I am still a beginner in Angular but I think I already did what I could.
I'm using Yeoman's angular generator and grunt. grunt serve works fine but grunt serve:dist doesn't. At first it has something to do with some of the partial templates not getting included into $templateCache but I already fixed it. The templates are now included in the final script.js and the network tab of chrome dev tools no longer reports 404s. Debugging ui-router in the dist version of the application gives me Unknown provider: aProvider <- a which is apparently not very helpful. This is turning into a guessing game really. Below are code snippets. I hope somebody can help me out. Any advice would be good.
index.html
<div id='main-container' ng-controller="AccountCtrl">
<div id='logged-in-container' ng-if="isLoggedIn"><!-- container-fluid -->
<div id='left-sidebar' class="col-lg-2 bg-dark-blue">
<div id='left-sidebar-navigation' ng-controller="SidebarNavigationCtrl">
<left-Sidebar-User-Profile></left-Sidebar-User-Profile>
<left-Sidebar-Navigation></left-Sidebar-Navigation>
</div>
</div>
<div id='main-container-body' class="col-lg-10" ui-view >
</div>
</div>
<div id='logged-off-container' ng-if="!isLoggedIn">
<div class="col-lg-12" ui-view >
</div>
</div>
</div>
Please note the directives left-Sidebar-User-Profile and left-Sidebar-Navigation works. Only the ui-view doesn't.
app.js
$stateProvider
.state('login', {
url:'/',
templateUrl: 'views/login.html',
controller: 'AccountCtrl',
controllerAs: 'main',
resolve: resolveLoggedIn
});
I already tried changing the code above to the format like views: { 'login': { url: ... } } which I believe is the correct thing but I got the same behavior so I reverted my changes.
Gruntfile.js is here as it's pretty long.
Thanks in advance folks.
This might be occuring because your angular code is not mininfication ready. For a better insight to the same, see this.
You should consider using something such as grunt-ng-annotate

How can I read URL parameters in AngularJS?

I'm trying to make a blog using AngularJS. The home page queries a third party service of mine that returns an array of all my articles/posts. I am displaying shortened versions of these posts on the home page, and want to have "read more" under each post that passes that post's ID through a URL parameter to another HTML page:
index.html:
<div ng-controller="blogCtrl" id="blog">
<div class="post" ng-repeat="post in posts">
<div class="header">
<h1>{{ post.fields.title }}</h1>
<p class="date">{{ post.sys.createdAt | date}}</p>
</div>
<p>{{ post.fields.body | cut:true:1600:' ...'}}</p>
read more
</div>
</div>
What do I need to do in post.html so that I can read the value of id in the URL parameter? Do I need to create a new angularJS app in post.html?
edit:
I've changed the read more link to <a href="post/{{post.sys.id}}"> and i am trying to set up the following route:
app.config(function($routeProvider){
$routeProvider
.when('/post/:postid',{
templateUrl: '/post.html',
controller: 'postCtrl'
})
});
However, clicking the "read more" link doesn't load up post.html, but instead a page that says File not found: /post/2B1K9K2DHqsYaGYcms2YeW. The route doesn't seem to be getting properly set up, since post.html isn't getting loaded.
This isn't all that hard to do, but you need to have routing set up on your app. You can create this functionality in your existing app, or separate it into a new one, it's up to you. Here are the relevant things you'll need to include in your code:
In your app include ngRoute as a dependency:
var myApp = angular.module('myApp', ['ngRoute']);
Also include routing config for your app:
myApp.config(function($routeProvider){
$routeProvider
.when('/someroute', {
templateUrl: 'someFolder/withSomeFile.html'
}
.when('/someroutewithparamters/:aftercolonisparameter', {
templateUrl: 'someFolder/post.html'
}
});
You can include a default route as well, but it's not necessary if you'd rather not. Be sure to include angular-route.js in your index.html for this to work.
Now in your controller you can simply do something like:
myApp.controller('postCtrl', function($routeParams, $scope, postFactory){
$scope.post = postFactory.functionToLoadPost($routeParams.aftercolonisparameter);
});
Obviously this will be different for your implementation based on how everything is set up, and you'll probably want to pick better names for your elements than I did, but those are the things you'll need in place to make this work. It's actually pretty straightforward.

Different states don't show ui-views

Intro
I'm using AngularJS with the AngularUI module to build an admin interface with several views.
I have a simple Layout for public pages which has one ui-view and another one for admin pages which has four ui-views (header, sidebar, main, footer).
Problem
The problem I have is if I set the ui-view main the public state won't display the login view, but if I won't set the ui-view main the public state will display the login view. The header, sidebar and footer work with any setting. It seems some setting is overriding another even I tried to set absolute names. Could someone explain what's going on here?
ui-view="main" ==> Login doesn't show
ui-view="" ==> Login shows
Visual layout:
Source code (index.html):
<body>
...
<div ui-view="public">
</div>
<div class="admin">
<div ui-view="header"></div>
<div ui-view="sidebar"></div>
<div class="container" style="margin-top:60px" ui-view="">
<!-- ^ add main here -->
</div>
<div ui-view="footer"></div>
</div>
...
</body>
Code example
I set up a minimal full code example to outline the problem:
Plunker Edit
Plunker Run
I've played around with your demo a little bit and had a look at the ui-router documentation.
If you change your 'public' state as shown below then it seems to work.
Original:
.state('public', {
url: '/login',
title: 'Login',
templateUrl: 'login.html'
})
Updated:
.state('public', {
url: '/login',
views: {
'main#': {
title: 'Login',
templateUrl: 'login.html'
}
}
})
Here is an updated plunkr:
http://plnkr.co/edit/okBWMPpWysS9srKrcxeG?p=preview
Is that what you're trying to do, or are you trying to set up login as a nested view?

Angular.js - Two Concurrent But Exclusive Routes ($routeProvider)

<div id="header">
Header
</div>
<div id="wrapper">
<div id="slider" ng-view>
Slider
</div>
<div id="mainWindow" ng-view>
Main window
</div>
</div>
http://jsfiddle.net/abehnaz/k9Y4f/
I am working with a webapp that has two major views. The first is a main window (standard stuff), and the second is a "slider". The slider is more than a slide out menu (sometimes called a "shelf"). It has routing and secondary information associated with it.
In what seems to be the normal Angular paradigm, I would use a single ng-view in the main window, and that would populate the main window with the results of the $routeProvider's view template.
However, here I want to be able to ALSO have the slider have its own route. Angular does not seem to support this. I was thinking that I could potentially hack the functionality in by making a client side URL of the form:
www.app.com/MAINWINDOW/someView1/someView2/SLIDER/someViewa
Am I on the right track with this, or is there another functionality of Angular that I can use?
I would not recommend two routeParameters. Make your sidebar a service and put a controller on your wrapper, slider, and mainWindow. By having the ng-controller on #wrapper as well as the children, you can share data between the controllers (and in turn, inject the service into those controllers. I have done this and it was very successful. See an example below. In my code, my ng-view and routing returned everything within the <div ng-app="myApp">. You could easily put the ng-view in the MainCtrl and trigger routes from the sidebar.
In your template:
<div ng-app="myApp">
<div ng-view>
//Produced by routing
<div id="wrapper" ng-controller="RootCtrl">
<div id="Sidebar" ng-controller="SidebarCtrl">
...
<div ng-click="setUnit(mod.number, unit.number)">Unit 1</div>
...
</div>
<div id="mainWindow" ng-controller="MainCtrl">
</div>
</div>
</div>
</div>
In your javascript:
A service:
myApp.service('questionsSvc', function(Modules) {
var QuestionsSrc = {};
QuestionsSrc.questions = [];
var getQuestionsForModAndUnitFn = function(mod, unit) {
...bunch of code to have it populate QuestionSrc with questions
};
return {
getQuestionsForModAndUnit: getQuestionsForModAndUnitFn,
Questions: QuestionsSrc
};
});
For Controllers:
function RootCtrl($scope) {
$scope.data = {};
}
function SidebarCtrl($scope, Modules, questionsSvc) {
$scope.setUnit = function (mod, unit) {
questionsSvc.getQuestionsForModAndUnit(mod, unit);
$scope.data.questions = questionsSvc.Questions.questions;
//$scope.data.questions was used in the MainCtrl window to do an ng-repeat on the json array of questions bound to this model.
}
};
function MainCtrl($scope){
...whatever you need to manipulate the code...
}
With this example, I am sharing information across Controllers. The magic is with the $scope.data = {}; from the RootCtrl. It allows me to attach questions to the $scope based on an action in the Sidebar (clicking a label) and use that same $scope in the MainCtrl to display the questions in a pretty format. With what I just showed, I did not have to use $routeParameters to pass variables to go to another page (such as module and quiz) but I could have done so as you asked but would have had the sidebar ng-click change routes.
Hope this helps.
One solution is to use Angular UI router:
AngularUI Router is a routing framework for AngularJS, which allows
you to organize the parts of your interface into a state machine.
Unlike the $route service in Angular core, which is organized around
URL routes, UI-Router is organized around states, which may optionally
have routes, as well as other behavior, attached.
States are bound to named, nested and parallel views, allowing you to
powerfully manage your application's interface.
Just to give a flavor for how you could use AngularUI Router- It supports multiple named views (which you can read more about under "Multiple & Named Views" in their docs). So for instance you can use ui-view with names:
<div id="wrapper">
<div id="slider" ui-view="slider">
Slider
</div>
<div id="mainWindow" ui-view="main">
Main window
</div>
</div>
Then within config you can attach states to various routes and specify what each view should display for that state.
myapp.config(function($stateProvider, $urlRouterProvider){
$stateProvider
.state('index', {
url: "/index",
views: {
"Slider": {
templateUrl:"route1.viewA.html"
},
"Main": {
templateUrl:"main1.viewA.html"
}
}
})
.state('slider2', {
url: "/slider2",
views: {
"Slider": {
templateUrl:"route2.viewA.html"
},
"Main": {
templateUrl:"main1.viewA.html"
}
}
})
There's a variety of other ways you could use AngularUI Router though. For instance, you may be able to get away with just using nested routes- which they recommend trying first.
Here's a couple more good reference material you might check out:
http://joelhooks.com/blog/2013/07/22/the-basics-of-using-ui-router-with-angularjs/
http://www.ng-newsletter.com/posts/angular-ui-router.html

Categories

Resources