I'm working on revamping an old AngularJS application including a component based layout. The issue I'm having is that nesting a component within a component doesn't seem to work.
Routing:
.state('mainApp', {
url:mapPath(""),
component: 'main'
})
.state('mainApp.project', {
url: "/project",
component:'project'
})
Main component HTML:
<div class="all-wrapper solid-bg-all" >
<div class="layout-w">
<nav-bar></nav-bar>
<div class="content-w">
<top-bar></top-bar>
<div class="content-i">
<div class="content-box">
<h1>main</h1>
<div ui-view></div>
</div>
</div>
</div>
</div>
</div>
Using standalone routes for main or project works fine. Main even loads in perfectly on the index on a ui-view there. But main.project state only displays a blank screen with no errors. The constructor in project is also not being called. When I inspect the page, it just shows the index without main in the first ui-view. Any ideas on what is causing this weird problem? Kind of losing my mind since it was working before without components but with controllers.
I've even tried it with template: '<h1>test</h1>' and that doesn't seem to work. ES6 doesn't seem to be the problem as well, just converted everything back to plain JS.
Resolved: error was based on the application: Turned out it caught any transition, checked if the user was authenticated and if not sent them to login. However the login state was broken, which resulted in a blank page.
Related
I have an angular 2 app with authentication, using this html as the main layout
<div *ngIf="auth.loggedIn" class="container">
<router-outlet></router-outlet>
</div>
<div *ngIf="!auth.loggedIn" class="login">
<router-outlet></router-outlet>
</div>
Yet when I login to the app I get the Error: Cannot find primary outlet to load error. This error is gone when I reload the page, but keeps happening when I login without refreshing the page after. What am I doing wrong?
There should be one <router-outlet></router-outlet> ,
in your code there is no meaning of putting two <router-outlet></router-outlet> ,
Logically it does nothing.
You should put all your conditions within , your component html , not into the root html part , as per your code.
I have a container component that has 2 other controllers nested in it. I have them set up like so
container -> component1 and container -> component2
My train of thought here was that I could transclude the HTML from my page into my container component.
<container> <component1></component1> <component2></component2></container>
and then in the container HTML <div ng-init="vm.init()" ng-transclude></div>
Problem is, my container isn't running at all, I added a console log to its init function and no code is running. While component1 and component2 run their init's.
Seems to be a large amount of documentation covering older angular versions. Which tell me that they need to be nested like so <div ng-controller="parentController"> <div ng-controller="childController"></div> </div
How do you nest components into each other in 1.5?
Looks like the issue was that I was attempting to put a ng-init and ng-transclude in the same element. My guess is that ng-transclude overrides everything in the element it is on.
so I moved the ng-init to another element and its working fine
<div ng-transclude ng-init="vm.init()"></div>
changed to
<div ng-init="vm.init()"> <section ng-transclude ></section> </div>
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 my application I have an index.html file where i have loaded all the required scripts and the body contains am empty ng-view whose content will update based on the route url.
The first page is a landing page where I'am showing a button to the user, clicking on which am showing Login Page, by changing the path value of $location.
On Successful login a dashboard page should come where header, sidebar footer area is going to be fixed and only the center area is going to be changed based on the menu clicks which is there in header section, by changing the route value
so the center area i declared as
when am trying to load the dashboard.html page it is going to infinite loop and when am removing the center div which is nothing but an empty view , my view is rendering fine. So the problem is with using the
Can anyone suggest me whether my understanding is corect ??
If yes please suggest me how to achieve my requirement...
index.html
<div class="row">
<div data-ng-view=""></div>
</div>
dashBoard.html
<div class = "row">
<header div here>
<div>
<sidebar div>
**<div data-ng-view = ""></div>** which is not working
</div>
<footer div here>
</div>
I have provided the html code
Thanks
What you're trying to do is not supported by the default router. You can try ui-router which supports multiple and nested views. You can see an example here http://plnkr.co/edit/7FD5Wf?p=preview. The index.html contains the main view.
<body ng-controller="MainCtrl" class="container">
<div ui-view></div>
</body>
Inside contacts.html there is another view
<h1>My Contacts</h1>
<div ui-view></div>
Try checking the difference between route provider and state provider.
Here's a link to ease your search.
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.