I have an Angular app with several nested controllers and views. I implemented infinite scrolling in it closely based on this tutorial for ngInfiniteScrolling: http://binarymuse.github.io/ngInfiniteScroll/demo_async.html
So I have a service that loads items into an array at $scope.content.items. Then there's an ng-repeat element that shows each result.
$scope.content = new Content()
$scope.content.loadMore( $scope.currentStream, 2 ) // this part is actually called in the HTML, but while debugging I've just done it in the controller
Now I want to implement search, and instead of making another search page, just have the items load in place of the current list of items. Basically to take the place of $scope.content.items.
So I built an identical controller, but now calling my search API. I use ng-change to see if someone has typed in the search box, then within the function that calls, do
$scope.search = function() {
$scope.content = new Search()
$scope.content.load( $scope.query )
}
I can see that this works in the console, that it replaces $scope.content.items, by doing this in the browser console:
var scope = angular.element($('[ng-controller=HomeController]')).scope()
scope.content.items
That shows me the array of objects I expect in each case (either before triggering ng-change="search()" or after). But the page itself does not update. It just shows the stuff from the Content() service.
Likewise, if I replace the above two lines from my controller with these below, it shows the content from the Search() service:
$scope.content = new Search()
$scope.content.load( 'thom' )
Long story short, I feel like the services and API work, but the page is not updating when I change the $scope.content.items array used by ng-repeat.
Here is the HTML
<div class="panel panel-item" ng-repeat="item in content.items" ng-hide="hideItem">
<h2 ng-hide=" item.stream == 'read' " data-ng-bind="item.title"></h2>
<a ng-click="openReaderModal( item )" class="cursor-pointer" ng-show=" item.stream == 'read' ">
<h2 data-ng-bind="item.title"></h2>
</a>
// ...
<div class="clearfix"></div>
</div>
Fixed it, somehow. Here is my routes from app.config() before:
$stateProvider
// ...
.state( 'app', {
url: '/app',
templateUrl: 'app/views/app.html',
controller: 'HomeController'
})
.state( 'app.home', {
url: '/main',
templateUrl: 'app/views/home.html',
controller: 'HomeController'
})
.state( 'app.profile', {
url: '/profile',
templateUrl: 'app/views/profile.html',
controller: 'ProfileController'
})
.state( 'app.read', {
url: '/read',
templateUrl: 'app/views/stream-content.html',
controller: 'HomeController'
})
.state( 'app.watch', {
url: '/watch',
templateUrl: 'app/views/stream-content.html',
controller: 'HomeController'
})
.state( 'app.listen', {
url: '/listen',
templateUrl: 'app/views/stream-content.html',
controller: 'HomeController'
})
And here's after:
$stateProvider
// ...
.state( 'app', {
url: '/app',
templateUrl: 'app/views/app.html',
controller: 'HomeController'
})
.state( 'app.home', {
url: '/main',
templateUrl: 'app/views/home.html'
})
.state( 'app.profile', {
url: '/profile',
templateUrl: 'app/views/profile.html',
controller: 'ProfileController'
})
.state( 'app.read', {
url: '/read',
templateUrl: 'app/views/stream-content.html'
})
.state( 'app.watch', {
url: '/watch',
templateUrl: 'app/views/stream-content.html'
})
.state( 'app.listen', {
url: '/listen',
templateUrl: 'app/views/stream-content.html'
})
And it works. If anyone can provide an explanation, I'll credit them the answer.
The routing in angular works like this.
When we provide a controller for the $stateProvider its actually considered as a new constructor (new keyword as in java) thus the data is re-initiated to defaults.
The new constructor will be the child to itself, to access the parent controller one can use the $parent
Related
I use library "ui-router" in angular. I have problem in route page when I route to other page till when load controller last page show and at the same time 2 page show in one page and when load page, last page remove.
How to solve problem delay ?
app.config([
"$stateProvider", "$urlRouterProvider",
function (stateProvider, urlRouterProvider) {
urlRouterProvider.otherwise("/dashboard");
stateProvider
.state("Dashboard",
{
url: "/dashboard",
templateUrl: "/Modules/Dashboard/Partials/dashboard.html",
controller: "DashboardCtrl as self"
})
.state("Deposit",
{
url: "/dashboard/desposit",
templateUrl: "/Modules/Dashboard/Partials/deposit.html",
controller: "DepositCtrl as self"
})
.state("PeymentRequest",
{
url: "/dashboard/peymentRequest",
templateUrl: "/Modules/Dashboard/Partials/peymentRequest.html",
controller: "PeymentRequestCtrl as self"
})
.state("ChangeBroker",
{
url: "/dashboard/changeBroker",
templateUrl: "/Modules/Dashboard/Partials/changeBroker.html",
controller: "ChangeBrokerCtrl as self"
});
}
]);
I am trying to insert views inside view. But it is working only at the defined state but when I trying to change the view with the help of ngClick the state lost the path.
It is like
View 1
--Sub View 1.1
------Sub Sub View 1.2
But only one sub view will appear that too based on click.
Code is here
.config(function($stateProvider, $urlRouterProvider) {
//$urlRouterProvider.otherwise('/login');
$stateProvider
.state('login',{
url:'/login',
templateUrl: 'partials/login.html'
})
.state('home',{
url:'/home',
views:{
'':{templateUrl:'partials/home.html'},
'grid#home':{templateUrl:'partials/home-grid.html'},
'list#home':{templateUrl:'partials/home-list.html'},
},
controller: 'homeController'
})
})
And my Controller
.controller('homeController', function($rootScope, $scope, $location){
$rootScope.bodyClass = "backround-img1"
$scope.gridClick = function(){
$scope.Tview = 'grid#home'
}
$scope.listClick = function(){
$scope.Tview = 'list#home'
}
}) ;
and in my Main View i have declared the model as below:
<a ng-Click="gridClick()">Grid</a>
<a ng-Click="listClick()">List</a>
----------------------------------------
<div ui-view="{{Tview}}"></div>
Suggesting you with
$state.go('stateName');
You can use something like this in your controller
$scope.changeView=function()
{
$state.go('new');
}
The config should be
$stateProvider
.state("home", {
url: "/",
templateUrl: "newView.html",
controller: "MainCtrl",
})
.state("new", {
url: "/",
templateUrl: "someOtherView.html",
controller: "MainCtrl",
});
Here is the LIVE for your code
I'm using UI-Router module for routing. I have 2 states that router should match the urls with them according to nested routes laws :
// Dashboard
.state('dashboard', {
url: "/dashboard",
templateUrl: "dashboard/views/index.html",
controller: "DashboardController",
...
})
// Users
.state('users', {
url: "/users",
templateUrl: "users/views/index.html",
controller: "UsersController",
...
})
// Single User
.state('users.id', {
url: "/{id:(?:[a-z0-9_-]{3,16})}",
templateUrl: "users/views/show.html",
controller: "UserController",
...
})
also I have set a default route :
$urlRouterProvider.otherwise("/dashboard");
Problem :
when I go to http://127.0.0.1:8000/app/#/users/testuser123, it shows index.html from users state instead of show.html from users.id state. What's the Problem ?
You should add users within your url definition for users.id if you call http://127.0.0.1:8000/app/#/users/testuser123
.state('users.id', {
url: "/users/{id:(?:[a-z0-9_-]{3,16})}",
templateUrl: "users/views/show.html",
controller: "UserController",
...
})
Consider this code:
bank.config(function($stateProvider) {
$stateProvider
.state('main.bank', {
url: '/',
controller: 'BankCtrl',
resolve: {
money: function(bankResource) {
return bankResource.getMoney();
},
templateUrl: 'bank/bank.html'
});
});
Above I render the bank.html template once resolve is finished executing.
I want to render a specific template depending on what is returned from my money function.
Example:
if money returns an object with items, render bank.html
if money returns an empty object, then return empty-bank.html
How can I achieve this within my $stateProvider? Or would it even make more sense for it to be in a directive?
Move your resolve code to parent controller, create two child routes one for each of bank.html and empty-bank.html and route based on the result of resolve, something like this -
.state('main', {
url: '/',
controller: 'MainCtrl',
resolve: {
money: function(bankResource) {
return bankResource.getMoney();
}
})
.state('main.bank', {
url: '/blank',
controller: 'BankCtrl',
templateUrl: 'bank/bank.html'
})
.state('main.emptybank', {
url: '/emptyblank',
controller: 'EmptyBankCtrl',
templateUrl: 'bank/empty-bank.html'
});
Inject the result of resolve into your controller and change state based on the output.
In the index.html of your main state, switch views based on the money variable. E.a.:
.state('main', {
url: '/',
controller: 'MainCtrl'
})
In your MainCtrl set a variable based on the output of your function:
$scope.money = "bank"
or
$scope.money = "emptybank"
Then in your index.html call a view:
<div ng-view="{{$scope.money}}"></div>
In your router:
.state('main.bank', {
url: '/bank',
views: {
bank: {
controller: 'BankCtrl',
templateUrl: 'bank/bank.html'
},
emptybank: {
controller: 'EmptyBankCtrl',
templateUrl: 'bank/emptybank.html'
}
}
})
Sorry in advance for any syntax errors. Typed it from head on my mobile phone.
But this should fix your problem and in the progress make it more "Angularesque" :-)
I am setting up a scaffold for an app with angular and angular-ui-router. I have it working however it seems to be adding a hash into my url (I'm running dev on localhost) localhost:9000/#/test. When I land on the main page it's just localhost:9000 and it still serves the main view content. I would like to get rid of the hash if possible.
So here is my setup:
In my index.html in the body I just have my nav and then the ui-view under that:
<div class="row">
<ul class="nav navbar-nav">
<li><a ui-sref="index">Home</a></li>
<li><a ui-sref="test">Test</a></li>
</ul>
</div>
<div ui-view=""></div>
and in my app.js I just have:
angular
.module('playApp', [
'ui.router'
])
.config(function($stateProvider) {
$stateProvider
.state('index', {
url: '',
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.state('test', {
url: '/test',
templateUrl: 'views/test.html',
controller: 'testCtrl'
});
});
So when I land, it's fine, but when I start using the nav I have set up, it adds the hashes to the url, would prefer not to have them if possible. Thanks!
Include $locationProvider and do $locationProvider.html5Mode(true); :
angular.module('playApp', ['ui.router'])
.config(function($stateProvider, $locationProvider) {
$stateProvider.state('index', {
url: '',
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.state('test', {
url: '/test',
templateUrl: 'views/test.html',
controller: 'testCtrl'
});
$locationProvider.html5Mode(true);
});
I also have an otherwise in there as well, so that if it can't find a specified route, it will just default back:
angular.module('playApp', ['ui.router'])
.config(function($stateProvider, $locationProvider, $urlRouterProvider) {
$stateProvider.state('index', {
url: '',
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.state('test', {
url: '/test',
templateUrl: 'views/test.html',
controller: 'testCtrl'
});
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/');
});
Inject $locationProvider into your config and set html5mode to true:
angular.module('playApp', [
'ui.router'
])
.config(function($stateProvider, $locationProvider ) {
$stateProvider
.state('index', {
url: '',
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.state('test', {
url: '/test',
templateUrl: 'views/test.html',
controller: 'testCtrl'
});
$locationProvider.html5Mode(true);
});
Make sure you adjust your .htaccess to handle this (rewriting back to root).
There is an alternative to html5Mode. But it has its drawbacks.
When defining ui-router states, the url option is not required. From that documentation:
You might create some child states without URLs, if it doesn’t make sense to bookmark those child states. The state machine transitions between url-less states as usual, but does not update the url when complete. You still get all the other benefits of a state transition such as parameters, resolve, and lifecycle hooks.
If you don't need to provide a URL for a state so that users can bookmark those states, you can omit the url option. The URL won't change.