Multiple Views with nested views Angular - javascript

So first off, I'm working on this for a project at work, but none of us have any idea how to do it, so it might be kind of vague.
Here is the template of how it is going to look: Template
So View A & B are going to have 3 states in them that will change the content of the view based on which one is selected
The problem I'm having is that only 1 view ever shows up and it is a test template for now because I don't have those views built but none of the sub views of View A ever show up.
HTML
<div id="main">
<div ui-view="viewa" class="col-sm-7">
<!--Content of ViewA supposed to be here-->
</div>
<div ui-view="viewb" class="col-sm-5">
<!--Content of ViewB supposed to be here-->
</div>
</div>
States:
$stateProvider.state("main", {
url: "/main",
views: {
"viewa#": {
abstract: true,
template: "<div ui-view></div>"
},
"viewb#": {
templateUrl: "btemps/default.html"
}
}
}).state("bobtheView", {
parent: "viewa",
//This is default for viewa
url: "/",
templateUrl: "atemps/bob.html",
controller: "bobController"
}).state("billtheview", {
parent: "viewa",
url: "/bill",
templateUrl: "atemps/bill.html",
controller: "billController"
}).state("joetheview", {
parent: "viewa",
url: "/joe",
templateUrl: "atemps/joe.html",
controller: "joeController"
});
//Supposed to route to viewa showing bobtheview and viewb showing the template
$urlRouterProvider.otherwise("/main/");
So when I go to the page and go to the root it redirects to the otherwise but nothing shows up, upon just going to main, only the viewb template shows up.
Any ideas? Any way I can format it better too? Is it better to go with "viewa.bobtheview" over having the parent attribute in the mix?
UPDATE: So I found a work around, I loaded each of the bobtheview, joetheview and billtheview in html partials, then I refactored it so the view state of viewa and viewb are controlled within a main template that includes the "ng-include" function to load the different templates, and since all of the data that is stored in those views is given via JSON rest requests, there is no change in the data bindings. The problem I'm facing now, is updating that "ng-include" on button click, I haven't done extensive research on it but I plan on doing so and I'll report back when/if I find something. If you have any ideas on this let me know! :D.

So I found a viable answer to the question at hand, after extensive research and asking around, I went with the option of having 1 Controller and configuration state
$stateProvider.state("main", {
url: "/",
controller: "mainController",
templateUrl: "temps/primary.html"
});
$urlRouterProvider.otherwise("/");
That went into the configuration settings, then my controller looked a little like this:
app.controller("mainController", ["$scope", "$state", "$stateParams", "$http", function($scope, $state, $stateParams, $http) {
$scope.viewatemp = $stateParams.at; //Numeric value to represent template url for viewa
$scope.viewbtemp = $stateParams.bt; //Numeric value to represent template url for viewb
//Do some other stuff here
});
Then the HTML of "temps/primary.html" looked a little something like this:
<div ui-view="viewa" class="col-sm-5" ng-include="viewatemp"></div>
<div ui-view="viewb" class="col-sm-7" ng-include="viewbtemp"></div>
I did a little manipulation of the numeric value of viewatemp and viewbtemp to get the actual URL, those are being loaded from a JSON request from my ASP.net WebApi 2 Restful service, but all in all, it is quick, rather simple and still gets the job done and allows for further enlargement of the project.
And that there in solved my problem, cool thing about this, I can have as many as these as I want because they are all separate states with nested "views"
If you do have a better answer, let me know! This is only what I found and what worked for me.

Related

Layout with form in angular Js

I am a beginner in angular Js and need some help / pointers. I want to create an application (SPA). Every page of an application has a header bar and in that header bar, I have a form (like search bar) where a user can add data and search. But I am not being able to approach.
How should my approach be so that this header is present in any page of my app and I must be able to search in any page. How can this be done without code repetition? I mean I dont want to create a directive and call it in every page. I want to know if there is a proper way to do it?
The app should be like Quora where the input field for question is present in any page.
Request you to not downvote it as I am naive in Angular and need some good help.
Thank you in advance.
Search for ui-router and define some states for your application, basically you have a main states which hold header and footer, and sub states that are children of your main state.
your markup would be like this:
<header></header>
<ui-view></ui-view>
<footer></footer>
and the header can contain the search form, and all sub states are loaded in mains <ui-view>
Have you checked out ui-router?
You could define a layout/root state whose template defines multiple named ui-views. The layout/root state could load the persisting elements (ex. the search input field) into one view, and child states could load the unique page content into another view.
ex. layout.html
<div class="layout">
<div class="search" ui-view="search"></div>
<div class="content" ui-view="content"></div>
</div>
ex. state configuration (in a module's config() function)
$stateProvider.state('root', {
url: '',
views: {
'main': {
templateUrl: 'layout.html'
},
'search#root': {
template: '<input type="text" ng-model="search.input" />',
controller: ['$scope', function($scope){
$scope.search = {
input: ''
};
}]
}
}
});
$stateProvider.state('root.page1', {
views: {
'content#root': {
template: '<p>This is the first page.</p>',
}
}
})
.state('root.page2', {
views: {
'content#root': {
template: '<p>This is the second page.</p>'
}
}
});
With that config, you would need to have in your main index.html:
<div ui-view="main"></div>
Plunker Demo

AngularJS nested controllers

I have an AngularJS app with 2 routes /home and /about.
I'm using ng-router and each route has different controllers HomeCtrl and AboutCtrl. The default route is /home.
The thing is that before display the content I want to add a preloader, just a simple div which will hide when the content is loaded.
<div class="myApp">
<div class="preloader"></div>
<div ui-view></div>
</div>
My question is, in which controller should I add this?
Should I add a new controller outside the ng-view for this kind of stuff?
Can someone explain me best practice?
I suppose the best way to do this is to use flag for data loaded indication directle in controller. So depend on this flag with ng-if directive you can show 'div' with loading indicator if dataLoadedFlag is false and div with your data otherwise.
You have ng-view, and your views render over there with its corresponding controller.
So the only thing you need ng-if
<ng-view>
<div ng-if="!$scope.contentIsReady">
content loading
</div>
<div ng-if="$scope.contentIsReady">
content here
</div>
</ng-view>
#Hiero In your case of course, you have to create new controller.
Also you can use nested views. Something like this:
$stateProvider.state('home', {
url: '/home',
views: {
"main": {
templateUrl: '....',
controller: '....'
},
'view-with-data#home': {
templateUrl: '...',
controller: '...',
}
}
});
See more at https://github.com/angular-ui/ui-router/wiki/Nested-States-&-Nested-Views

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.

best way of setting up 12 product pages in AngularJS with dynamic routing and templating

I'm somewhat new to AngularJS so I'd like to know whats the best way to architect the products section of my app.
So I have a main product page which will list and link to all my 12 products. Then each ind. product page will need to have the same format (i.e. product description, color, height etc.). This data will not be coming from a backend source. Its just plain HTML.
Whats the best way of setting things up to maximize code reuse? I'm thinking I want to do for the routing - /products/products.html to list all products and then something like /products/product1.html for an ind. product.
How can I make this all work in AngularJS?
Thanks!
For routing you will need to use the ng-view directive in your HTML. The simplest way I can think of is to create a div on the main page and assign it the directive ng-view. Then your Javascript file create a the routing. Below is a sample code just for reference purpose.
// YOUR HTML
<main class="cf" ng-view>
</main>
// YOUR JAVASCRIPT
var myApp = angular.module('myApp', ['ngRoute', 'appControllers']);
var appControllers = angular.module('appControllers', []);
myApp.config(['$routeProvider', function($routeProvider){
$routeProvider.
when("/products1", { templateUrl: "views/products1.html"}).
when("/products", { templateUrl: "views/products2.html"}).
when("/products3", { templateUrl: "views/products3.html"}).
otherwise({
redirectTo: "/login"});
}]);

How do I allow for clicking on each item/post, then viewing it in a new screen?

Im trying to build a simple tutorial app list of grocery items, and then clicking on it will lead to a new page showing the grocery goods in details, such as price, quantity left etc.
Currently, clicking on the comments button does nothing. I see a twitch in the URL but it reverts back to its original posts url. No syntax issues so far.
I suspect it might by either naming convention of the states or the angular.module definitions gone wrong. Can someone enlighten me please? Thanks!
This is the stateProvider codes
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('tab', {
url: '/tab',
abstract: true,
templateUrl: 'templates/tabs.html'})
.state('tab.posts', {
url: '/posts',
views: {
'tab-posts': {
templateUrl: 'templates/tab-posts.html',
controller: 'PostsCtrl'}}})
.state('tab.view', { //suspect error is here but various combos didnt work
url: '/posts/:postId',
views: {
'tab-view':{
templateUrl: 'templates/tab-showpost.html',
controller: 'PostViewCtrl'}}})
This is the postview.js file
var app = angular.module('app.controllers.view', []) //error even if remove this line
app.controller('PostViewCtrl', function ($scope, $stateParams, Post) {
$scope.post = Post.find($stateParams.postId);
});
This is the tab-showpost.html
{{ post.title }}
Back to Posts
This is the tab-posts.html
<form ng-submit="submitPost()">
<input type = "text" ng-model="post.title"/>
<input type = "text" ng-model="post.url"/>
<input type = "submit" value="Add Post"/>
</form>
<div ng-repeat="(postId, post) in posts">
{{ post.title }}
comments
</div>
I think it cannot resolve your url, maybe this has to do with the way you named your routes and how they inherit eachother. Shouldnt they url be #/tab/posts/{{ postId }} ?
Else you could try and see if it works with a ^ to make the route absolute and not relative to the parent.
So to make the url work, try
.state('tab.view', { //suspect error is here but various combos didnt work
url: '^/posts/:postId',
views: {
'tab-view':{
templateUrl: 'templates/tab-showpost.html',
controller: 'PostViewCtrl'}}})
Else it will take on the path relative to its parent, tab in this case if i am correct and thus have the url #/tab/posts/{{ postId }}.
Not completely sure that I understand your app structure, but here is a working example, which should follow your design
Firstly, because the 'tab' state is parent for both children tab.posts and tab.view, I placed both targets inside of the tabs.html:
<div>
<h3>Tabs</h3>
<hr />
<div ui-view="tab-posts"></div>
<div ui-view="tab-view"></div>
</div>
NOTE: in fact, there could be just one even unnamed template <div ui-view=""></div> and both states can target that like this views : { '' : {...
The way, how we can go to comments from a list view is expressed this way:
comments
<a ui-sref="tab.view({postId: postId})">comments</a>
The rest of your draft is mostly unchanged, just do not forget to reference all modules in the root one:
var app = angular.module('myApp', [
'app.controllers.view',
'ui.router'
]);
The working plunker is here
Instead of:
comments
I prefer using state names in refs so that the angular will resolve the url for you. It's simpler if you do:
<a ui-sref="tab.view({postId:postId})">comments</a>

Categories

Resources