Load multiple views using angularjs - javascript

I have a scenario like this:
Link1
Link2
<div id="child1"></div>
<div id="child2"></div>
When I click on link1 I expect to load View A in div child 1 and View B in div child2.
When I click on link2 I expect to load View C in div child 1 and View D in div child2
I'm using ngRoute (standard AngularJS router) in my app.
i.e: I expect a different set of views for different links. How can this be accomplished using AngularJS. I understand that Angular does provide routing, but whatever examples I see online is only for a single view.
I have kept this scenario very simple. In reality it is a lot more complicated so I will not be able to combine 2 views into 1 for each link.

Here is a suggestion:
1) Make 4 templates (one per view):
viewA.html
viewB.html
viewC.html
viewD.html
2) Set 2 routes on your app (one per link):
$routeProvider.when('/page1', {
templateUrl: 'page1.html',
controller: 'Page1Ctrl'
}).when('/page2', {
templateUrl: 'page2.html',
controller: 'Page2Ctrl'
});
3) Include the views in page link1.html and link2.html
<!-- page1.html -->
<div id="child1" ng-include="'viewA.html'"></div>
<div id="child2" ng-include="'viewB.html'"></div>
<!-- page2.html -->
<div id="child1" ng-include="'viewC.html'"></div>
<div id="child2" ng-include="'viewD.html'"></div>
3) Set your <a> tags
Link1
Link2

Another suggestion, you can use ui-router and multiple named views it's easy to use and really powerful.
You can create your different view container using ui-view like this
<a href="#" >Link1</a>
<a href="#" >Link2</a>
<div ui-view="child1"></div>
<div ui-view="child2"></div>
And in you app.config, you can set for every states which template you want to load for the different views :
.state('report', {
views: {
'child1': { ... templates and/or controllers ... },
'child2': {}
}

Related

How to bootstrap component based angular 1 application?

Using angular 1.6, here are the components I need to have:
+-------------------+
|side| |
|bar | |
|... | view |
|... | |
|... | |
+-------------------+
side bar: placed on left. using ng-repeat and updates dynamically.
view: rest of the app. template is static but contents changes when click on side bar.
when the user clicks on each list <li> of side bar, it updates the view. only view content/model will change. not the html template.
Important: I just don't want to write a code in <body>. Would like to have sidebar in one html file and view in another associated with their controllers and render the whole app through ng-view in <body>.
The side bar updates dynamically so that I cannot specify state in config() for each.
any other standard architecture is appreciated.
As mentioned in the comments, there are multiple architecture and framework choices that can be made to implement the type of templating you're looking for. I'll provide a basic example based on something I've used in the past with angular, using ui-router and child/nested views.
Lets say you have an index.html like:
<body>
<div ui-view="header" class="header"></div>
<div ui-view="main" class="main"></div>
<div ui-view="footer" class="footer"></div>
</body>
The index page just has the layout for the most high level view, namely header, content and footer. If you have no need for header and footer, you can just ignore/remove it. Now the layout your are looking for, with a side bar on the left and the content on the right, will be placed within the main view. To do this lets declare another page which will define this structure, call it landing.html (use bootstrap for simplicity):
<div class="container-fluid">
<div class="row landingContainer">
<div class="col-md-2 col-sm-4 col-xs-3 sidebarSection">
<div class="row item" ng-click="landing.changePage('content1')">
<span>Show Content 1</span>
</div>
<div class="row item" ng-click="landing.changePage('content2')">
<span>Show Content 2</span>
</div>
<div class="row item" ng-click="landing.changePage('content3')">
<span>Show Content 3</span>
</div>
</div>
<div class="col-md-10 col-sm-8 col-xs-9 contentSection">
<div ui-view="content"></div>
</div>
</div>
</div>
You can think of this page as the root of your layout. The page is split into a left and right section using bootstrap columns. The left side contains the listing of all your content views. You can use li, i just prefer divs. The right side will be where the dynamic part of the page is, where the content will change based on the item selected in the side bar. Each component view is a child of the landing page, it inherits all the features of the parent and then adds its own content into the ui-view, similar to how landing.html added its content into the main ui-view. Now lets take a look at the ui-router config that makes all this work.
function routerConfig($stateProvider, $urlRouterProvider) {
$stateProvider
.state('landing', {
url: '/landing',
views: {
'header': {
templateUrl: 'app/components/header/headerPrivate.html',
controller: 'HeaderController',
controllerAs: 'header'
},
'main': {
templateUrl: 'app/landing/landing.html',
controller: 'LandingController',
controllerAs: 'dashboard'
},
'footer': {
templateUrl: 'app/components/footer/footer.html',
controller: 'FooterController',
controllerAs: 'footer'
}
}
})
.state('landing.content1', {
url: '/content1',
views: {
'content': {
templateUrl: 'app/content1/content1.html',
controller: 'Content1Controller',
controllerAs: 'content1'
}
}
})
.state('landing.content2', {
url: '/content2',
views: {
'content': {
templateUrl: 'app/content2/content2.html',
controller: 'Content2Controller',
controllerAs: 'content2'
}
}
})
.state('landing.content3', {
url: '/content3',
views: {
'content': {
templateUrl: 'app/content3/content3.html',
controller: 'Content3Controller',
controllerAs: 'content3'
}
}
})
$urlRouterProvider.otherwise('/');
}
Here you'll notice that the landing page route defines the configuration for the 3 main views, header, main and footer. The url path will be /landing. Then content1, content2 and content3 are defined as children by nesting them within landing using the dot notation: landing.content1. The url paths for each child will then resolve to /landing/content1, /landing/content2, landing/content3. So now anytime you navigate to those locations only the content for that specific child will be nested within the landing pages "content" ui-view and the remaining layout of the page stays the same.
For the sake of completion, this is how the landing controller might look:
function LandingController($state) {
var vm = this;
vm.changePage = function(page){
$state.transitionTo('landing.'+page, null, null);
}
}

Multiple partial views on AngularJS

I have an AngularJS application that has a list of contents on the menu. When the user clicks on an item on the menu, the content loads on the main view. There are multiple content types:
When "1" is clicked, a video is loaded. When "2" is clicked, a PDF document is loaded, and so on. Content types may repeat and be complex.
Now, I am setting $scope.content when an item is clicked and, depending on its contentType, I'm calling a different directive:
<div class="content" ng-switch on="content.contentType">
<div ng-switch-when="video">
<videoplayer-directive video="content"></videoplayer-directive>
</div>
<div ng-switch-when="pdf">
<pdfreader-directive pdf="content"></pdfreader-directive>
</div>
<div ng-switch-when="...">
<...-directive content="content"></...-directive>
</div>
</div>
Now I have two problems:
When the page is loaded, all the directive templates are automatically loaded. Even if I don't have a PDF in the menu, the pdf template and scripts will be loaded.
Searching for it, I learned that directives should be tiny, not entire modules of my app.
How do I rewrite the switch above so I can comply with the best practices and load the templates and scripts only when needed?
This is exactly what UI-Router is for: Angular UI Router
Decent tutorial on scotch.io
An easier drop-in replacement for your code may be to simply use ng-if. Ng-if won't instantiate the directive until it's called. Just make sure that your directives aren't transcluding the outer div- if that's the case, shut transclusion off, or add another div to wrap them.
<div class="content">
<div ng-if="content.contentType=='video'">
<videoplayer-directive video="content"></videoplayer-directive>
</div>
<div ng-if="content.contentType=='pdf'">
<pdfreader-directive pdf="content"></pdfreader-directive>
</div>
<div ng-if="content.contentType=='...'">
<...-directive content="content"></...-directive>
</div>
</div>

In AngularJs is possible inside a controller to load in a variable an external html template?

question for angularjs about the inclusion inside a controller of html templates to set into variables.This is the scenario.
I've a slider generated automatically with angularjs, and every slide is a page
<div ng-repeat="slide in sliders" onfinishrender id="slide-page-{{slide.id}}" class="slidepage" data-page-type="{{slide.type}}"></div>
Every slide/page is displayed alone and with all its content, while the others slides/pages are hidden.The content is loaded dynamically only the first time you navigate in the slide/page, and of course it is different for every template. Those base templates are managed with external html files: template.html, template-image.html, template-small.html ...
Then there is a contentController that load via ajax the data for every template:
// not relevant to post it
And a templateController that manages all data loaded into the slide/page template:
o_app.controller("newsroomCtrl", ['$scope', function($scope){
// function that retrieves the html for the content of a subpage
$scope.fn_get_html_template = function(a_response){
var a_posts = a_response.posts;
// loading template.html
// how to do that???
// loading template.html
}
}]);
And this is one of the html templates:
<div class="content-container newsroom" ng-controller="newsroomCtrl">
<ul class="newsmenu">
<li>
<button data-filter="all" class="filter active">All{{test}}</button>
</li>
<li>
<button data-filter=".news" class="filter">News</button>
</li>
</ul>
....
</div>
My goal is to be able to load dynamically the html template in the templateController, bind the $scope to the view, set into one variable and load it into one slide/page of the beginnign slider.
Do I miss something, how could I achieve my goal?
thanks in advance

Two ui-view in the same page AngularJs

I'm new in AngularJs and I have a problem,I have two ui-view in the same page, and when push in the one button for example for show the view goals, appear the form goal in the ui-view 1 and also in the second ui-view at the same time,I worked with states.I don't know how to do for when push one button only show the form belonging to one ui-view,
look my source:
HTML
<button class="btn btn-success"
ng-click="go('projectShow.milestones.reports')">New Report</button>
<div ui-view class="crearreport"></div>
<button class="btn btn-success"
ng-click="go('projectShow.milestones.goals')">New Goals</button>
<div ui-view class="creargoal"></div>
Controllerjs:
$scope.go = function(route){ $state.go(route); };
RouteJs:
.state('projectShow.milestones.goals', {
templateUrl: '../assets/projects/formulario.html', })
.state('projectShow.milestones.reports',{
templateUrl: '../assets/reports/formularioReport.html' })
Regards! and thanks for your time !
Since you have multiple ui-view directives you need to give each one a name so you can target them individually.
According to the ui-router wiki
You can only have one unnamed view within any template (or root html)
<!-- Unnamed -->
<div ui-view></div>
<!-- Named -->
<div ui-view="viewName"></div>
There are more details on how to setup ui-router & ui-view here.
https://github.com/angular-ui/ui-router/wiki/Quick-Reference#ui-view

AngularJS ui router - not showing nested partials views

I have an AngularJs app with start up page as index.html, by default the projects view will be displayed and on top of the page I am showing a icon to show the todo items (for the logged-in user) which I am using bootstrap's data-toggle dropdown. The issue is whenever I click the todo link the partial view (todo.html) is not showing. BTW, I am new to the angular world so please forgive me if there is anything silly. Please see the code below:
Index.html
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head></head>
<body>
<a data-toggle="dropdown" class="dropdown-toggle" ui-sref=".todo">
<i class="icon-tasks"></i>
<span class="badge badge-grey">4</span>
</a>
<div ng-view></div>
</body>
app.js
// For any unmatched url, redirect to /projects
$urlRouterProvider.otherwise("/projects");
//
// Now set up the states
$stateProvider
.state('projects', {
url: "/projects",
templateUrl: "/app/views/projects/projects.html",
controller: "projectController"
})
.state('projects.todo', {
url: "/todo",
templateUrl: "/app/views/todo/todo.html"
});
First of all replace ng-view with ui-view in the root template, cause it seems you want to use ui-router instead of ng-router.
Wrap the content of your template files with div of ui-view as a parent element.
/app/views/projects/projects.html
/app/views/todo/todo.html
<div ui-view>
... previously defined content ...
</div>
Let's say your view was
<div class="container">
<div class="page-header">
<h1>Title: {{title}}</h1>
</div>
</div
you need to add ui-view to the div
<div class="container" ui-view>
<div class="page-header">
<h1>Title: {{title}}</h1>
</div>
</div
or wrap your view with div containing ui-view descriptor in case your vie contains several tags.
I cannot show you an example since you did not provide content of view files.
/app/views/projects/projects.html
/app/views/todo/todo.html
The issue is that after fist template applying angular does not see the place to put new template anymore.
ui-router isn't really supposed to be used in this way. To integrate bootstrap with angular you want to look at UI Bootstrap - http://angular-ui.github.io/bootstrap/
Then to achieve your drop down, look at their basic examples. If you want to use separate view files to define your drop down content, you can use <div ng-include="'mycontent.html'"></div>.
ui-router is useful if you have a complex view hierarchy, where you are for example, looking for dynamic loading of children, while keeping parent states static.
In ui-router you defined all of this in the $stateProvider, so there you should define that you have a view that has another view belonging to it, example:
<!-- In index.html the main view that will have all the page views-->
<div id="main" ui-view="main"></div>
<!-- In todo.html with a partial with the dropdown code in dropdown.html -->
<h1> This is a nice todo drop down </h1>
<div id="todoDropDown" ui-view="todoDropDown"></div>
//In your app file
.state('projects.todo', {
url: '/todo',
views: {
'main#': {
templateUrl: '/app/views/todo/todo.html',
controller: 'TodoCtrl'
},
'todoDropDown#projects.todo': {
templateUrl: '/app/views/partials/dropdown.html'
}
}
})
"todoDropDown#projects.todo" This does the magic, it tells that this view has another view inside. And you can add controller to it and all other options you have in ui-router. In this way you can break up as much as possible reusable parts.

Categories