Angular-material infinite scroll and $http - angularjs

I've already tried to follow instructions in this question, but I'm stuck, so I had to ask this as a new question.
I am trying to create infinite scroll where a user can see his activities. Only 10 (10 is a hypothetical number here) activities will be shown at a time, so performance will be better.
I created a simple pagination on backend and it works as expected.
/feed/1 -> displays first 10 results (0-10)
/feed/2 -> displays 10 more (10-20)
/feed/3 -> displays 10 more (20-30)
Since I use $http, I couldn't find a way to mimick it, so I put it here as it is for now. There may be more than one issue here, I tried to be careful, though.
Here's my plunk : http://plnkr.co/edit/DLAMy56jwyeqYdN1kvT3?p=preview
Here's my code.
index.html
<!doctype html>
<html lang="en" ng-app="feed">
<head>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/angular_material/1.0.0/angular-material.min.css">
<meta charset="UTF-8">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-animate.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-aria.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-messages.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.8/angular-ui-router.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<div ui-view></div>
<!-- Everything is in template.html -->
</body>
</html>
template.html
<div class="virtualRepeatdemoInfiniteScroll">
<md-content layout="column">
<md-virtual-repeat-container id="vertical-container" flex>
<div md-virtual-repeat="FeedFlow in PostController.data" md-on-demand class="repeated-item" flex>
<div ng-repeat="text in FeedFlow.feed">
{{FeedFlow.id}} <!-- whose post is this? -->
{{text.status}} <!-- status -->
</div>
</div>
</md-virtual-repeat-container>
</md-content>
</div>
style.css
.virtualRepeatdemoInfiniteScroll #vertical-container {
height: 292px;
width: 400px;
}
.virtualRepeatdemoInfiniteScroll .repeated-item {
border-bottom: 1px solid #ddd;
box-sizing: border-box;
height: 40px;
padding-top: 10px;
}
.virtualRepeatdemoInfiniteScroll md-content {
margin: 16px;
}
.virtualRepeatdemoInfiniteScroll md-virtual-repeat-container {
border: solid 1px grey;
}
.virtualRepeatdemoInfiniteScroll .md-virtual-repeat-container .md-virtual-repeat-offsetter {
padding-left: 16px;
}
script.js
angular.module('feed', ['ui.router', 'ngMaterial']);
angular.module('feed').run(
['$rootScope', '$state', '$stateParams',
function($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}
]
)
.config(
['$stateProvider', '$urlRouterProvider', '$locationProvider',
function($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
$stateProvider
.state('posttest', {
url: '/post1',
templateUrl: 'template.html',
resolve: {
data: 'vm.data',
},
controller: 'PostController'
});
}
]
);
// This is how I normally fetch a feed page. (PostData factory)
// I commented out this part and tried to inregrate it below at PostController section.
/*
angular.module('feed').factory('PostData', ["$http", function($http) {
return $http.get("/feed/1").then(function(response) {
return response.data;
});
}]);
*/
// This is the part I couldn't inregrate it.
// Original link is here : https://material.angularjs.org/latest/demo/virtualRepeat
// I'm trying to implement Infinite Scroll, a demo can be seen below
// http://codepen.io/anon/pen/NxeVwo
angular.module('feed').controller('PostController', ['$scope', '$http', function($scope, $http, $timeout) {
var vm = this;
vm.data = {
numLoaded_: 0,
toLoad_: 0,
items: [],
// Required.
getItemAtIndex: function(index) {
if (index > this.numLoaded_) {
this.fetchMoreItems_(index);
return null;
}
return this.items[index];
},
// Required.
getLength: function() {
return this.numLoaded_ + 1;
},
fetchMoreItems_: function(index) {
if (this.toLoad_ < index) {
this.toLoad_ += 1;
$http.get('/feed/' + this.toLoad).then(angular.bind(this, function(response) {
this.items = this.items.concat(response.data);
this.numLoaded_ = this.toLoad_;
}));
}
}
};
}]);

Related

how to write a rowtemplate when pinning exsits

when I set pinning and rowTemplate together,the rowTemplate repeat 3 times in single row
I think it is influenced by the pinning col,but i don't know how to fix it
here's the plunker: http://plnkr.co/edit/XoXMbmqa1IjegT1RQ297?p=preview
var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.pinning']);
app.controller('MainCtrl', ['$scope', '$http', '$log', function ($scope, $http, $log) {
$scope.gridOptions = {};
$scope.gridOptions.columnDefs = [
{ name:'id', width:50, enablePinning:true, hidePinLeft: false, hidePinRight: true },
{ name:'name', width:100, pinnedLeft:true },
{ name:'age', width:100, pinnedRight:true },
{ name:'address.street', width:150 },
{ name:'address.city', width:150 },
{ name:'address.state', width:50 },
{ name:'address.zip', width:50 }
];
$scope.gridOptions.rowTemplate='<div>helloworld</div>'
$http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/500_complex.json')
.then(function(response) {
$scope.gridOptions.data = response.data;
});
}]);
.grid {
width: 100%;
height: 400px;
}
<!doctype html>
<html ng-app="app">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.7.0/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.7.0/angular-touch.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.7.0/angular-animate.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.7.0/angular-aria.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/csv.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/pdfmake.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/vfs_fonts.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/lodash.min.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/jszip.min.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/excel-builder.dist.js"></script>
<script src="http://ui-grid.info/release/ui-grid.js"></script>
<link rel="stylesheet" href="http://ui-grid.info/release/ui-grid.css" type="text/css">
<link rel="stylesheet" href="main.css" type="text/css">
</head>
<body>
<div ng-controller="MainCtrl">
<div ui-grid="gridOptions" class="grid" ui-grid-pinning></div>
</div>
<script src="app.js"></script>
</body>
</html>
I'm trying to make a table with multi headers to show date info,and each row has a name as the first column ,the second column is a line chart which can show business data.
I draw a pic to show this
Assuming you can do without pinning, I would remove the pinning extension from your grid. This makes working with header templates easier... You would otherwise run into the same issue with your header (three repeated headers).
See this plunker: http://plnkr.co/edit/nvuUKIQczdY2E6KuMEVG?p=preview
I removed pinning, removed rowTemplate, used a single headerCellTemplate (placeholder) to accomodate your calender header, and used a cellTemplate to accomodate you graph logic.
Html:
<div ng-controller="MainCtrl">
<div ui-grid="gridOptions" class="grid"></div>
</div>
Javascript:
var app = angular.module('app', ['ngTouch', 'ui.grid']);
app.controller('MainCtrl', ['$scope', '$http', '$log', function ($scope, $http, $log) {
$scope.gridOptions = {};
$scope.gridOptions.columnDefs = [
{ field:'id', name:'id', width:'25'},
{ field:'name', name:'name', width:'*' },
{ name:'chart', headerCellTemplate:'<div>Include header code here', width:'*', cellTemplate: '<div>include graph code here</div>' }
];
$http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/500_complex.json')
.then(function(response) {
$scope.gridOptions.data = response.data;
});
}]);
Hope I interpreted your goal correctly and I hope this helps :)

Why ng-class is not applied as per the current state of ui router?

My application has two different views (page1 and page2), which has been configured with ui-router's stateProvider. I want to apply a css on the body based on what page I am looking at. If I am looking at page1 I want to apply class1 to the body of the page and class2 for page2.
To achieve this I am using the ng-class directive of the angularjs. The value of the ng-class directive is being set as per the current state of the ui-router.
Here is the example code for it, the problem is that the expression inside the ng-class doesn't get evaluated, so my css doesn't get applied.
Can anyone point me what I am doing wrong ?
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.4.2/angular-ui-router.min.js"></script>
<style media="screen">
h2 {
margin: 5px 5px 5px 5px;
}
body {
display: flex;
flex-direction: column;
}
.class1 {
align-items: flex-start;
}
.class2 {
align-items: center;
}
</style>
</head>
<body ng-app="graceApp" ng-class="$state.current.data.bodyClass">
<div ui-view style="display: flex"></div>
<script>
angular
.module('graceApp', [
'ui.router'
])
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('page1', {
url: '/page1',
template: '<h2>This is page1</h2> <h2>Item1</h2> <h2>Item2</h2>',
data: {
bodyClass: 'class1'
}
})
.state('page2', {
url: '/page2',
template: '<h2>This is page2</h2> <h2>Item1</h2> <h2>Item2</h2>',
data: {
bodyClass: 'class2'
}
});
$urlRouterProvider.otherwise('/page1');
});
</script>
</body>
</html>
The $state service is not available in HTML. You just have access in the html to the variables set in the scope so a quick fix would be to set the state in the rootScope then you could access it in the HTML.
$rootScope.$state = $state;
I'm not sure whether $state service is accessible in HTML like this. Did you consider to create some function in your controller that will return $state.current.data.bodyClass and then, you link that function into ng-class
function getClass() {
return $state.current.data.bodyClass;
}
HTML:
<body ng-app="graceApp" ng-class="getClass()">
If you are using controllerAs pattern, make sure you make this function public and use it inside HTML with controller alias.
You can't access $state in html directly, so you need to define another scope variable in controller like
<!doctype html>
<html ng-app="graceApp">
<head>
<meta charset="utf-8">
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.4.2/angular-ui-router.min.js"></script>
<style media="screen">
.class1 {
background-color: red;
}
.class2 {
background-color: green;
}
</style>
</head>
<body ng-controller="mainController" ng-class="bodyClass">
<div ui-view></div>
<script>
angular.module('graceApp', ['ui.router']).config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('page1', {
url: '/page1',
template: '<h2>This is page1</h2> <h2>Item1</h2> <h2>Item2</h2>',
data: {
bodyClass: 'class1'
}
})
.state('page2', {
url: '/page2',
template: '<h2>This is page2</h2> <h2>Item1</h2> <h2>Item2</h2>',
data: {
bodyClass: 'class2'
}
});
$urlRouterProvider.otherwise('/page1');
});
angular.module("graceApp").controller("mainController", function($rootScope, $scope) {
$rootScope.$on("$stateChangeSuccess", function(event, current, params) {
console.log(current.data.bodyClass);
$scope.bodyClass = current.data.bodyClass;
});
});
</script>
</body>
</html>

how to implement controller with ui-router angularJS

im trying to use ui-router in AngularJS for the first time, but i think ive set up script.js file incorrectly. Any help would be appreciated. Is the problem with the app.controller?? Where have i gone wrong?
var app = angular.module("catalogue", ['ui.router'])
app.config(function($stateProvider) {
var homeState = {
name: 'home',
url: '/home',
templateUrl: 'home.html',
controller: 'HomeCtrl'
},
var category1State = {
name: 'category1',
url: '/category1',
templateUrl: 'category1.html',
controller: 'Category1Ctrl'
},
var category2State = {
name: 'category2',
url: '/category2',
templateUrl: 'category2.html',
controller: 'Category2Ctrl'
},
var category3State = {
name: 'category3',
url: '/category3',
templateUrl: 'category3.html',
controller: 'Category3Ctrl'
};
otherwise({redirectTo: '/home' })
$stateProvider.state(homeState);
$stateProvider.state(category1State);
$stateProvider.state(category2State);
$stateProvider.state(category3State);
});
app.controller('HomeCtrl', ['$scope', '$http', function($scope, $http, $stateParams) {
$http.get('home.json').then(function(response){
$scope.home = response.data;
});
}])
app.controller('Category1Ctrl', ['$scope', '$http', function($scope, $http, $stateParams) {
$http.get('category1.json').then(function(response){
$scope.category1 = response.data;
});
}])
app.controller('Category2Ctrl', ['$scope', '$http', function($scope, $http, $stateParams) {
$http.get('category2.json').then(function(response){
$scope.category2 = response.data;
});
}])
app.controller('Category3Ctrl', ['$scope', '$http', function($scope, $http) {
$http.get('category3.json').then(function(response){
$scope.category3 = response.data;
});
}])
and my index.html
<!DOCTYPE html>
<html lang="en" ng-app="catalogue">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<title> Catalogue </title>
<!-- Bootstrap core CSS -->
<link href="bootstrap.min.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="style.css" rel="stylesheet">
</head>
<body>
<div class="container">
<!-- The justified navigation menu is meant for single line per list item.
Multiple lines will require custom code not provided by Bootstrap. -->
<div class="masthead">
<h3 class="text-muted"> Catalogue </h3>
<nav>
<ul class="nav nav-justified">
<li><a ui-sref="home" ui-sref-active="active">Home </a></li>
<li><a ui-sref="category1" ui-sref-active="active">Category1</a></li>
<li><a ui-sref="category2" ui-sref-active="active">Category2</a></li>
<li><a ui-sref="category3" ui-sref-active="active">Category3</a></li>
</ul>
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="text" placeholder="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</nav>
</div>
<div ng-controller="HomeCtrl">
<div ng-view></div>
</div>
<!-- Site footer -->
<footer class="footer">
<p>© 2017 Company, Inc.</p>
</footer>
</div> <!-- /container -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular-route.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.8/angular-ui-router.min.js"></script>
<script src="script.js"></script>
<ui-view></ui-view>
</body>
</html>
Heres an example codepen to get you started, hope it helps:
(function() {
'use strict';
function config($stateProvider, $urlRouterProvider, $httpProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
controller: 'MainController as vm'
})
.state('other', {
url: '/other',
controller: 'OtherController as vm'
});
$httpProvider.interceptors.push(function() {
return {
response: function(res) {
/* This is the code that transforms the response. `res.data` is the
* response body */
res.data = {
data: data
};
res.data.meta = {
status: res.status
};
console.log(JSON.stringify(res));
return res;
}
};
});
}
function cacheFactory($cacheFactory) {
return $cacheFactory('headlineCache', {
capacity: 1
});
}
function MainController(httpInterceptor) {
var vm = this;
console.log('MainController');
vm.title = 'Main Title';
httpInterceptor
.consoleLog();
}
function OtherController() {
var vm = this;
vm.title = 'Other Title';
console.log('OtherController');
}
function httpInterceptor($http) {
return {
consoleLog: consoleLog
};
function consoleLog() {
return console.log('httpInterceptor');
}
}
function contactCard() {
return {
scope: false,
restrict: 'E',
template: '<div><h2></h2><p></p></div>'
};
}
angular
.module('app', ['ui.router'])
.config(config)
.controller('MainController', MainController)
.controller('OtherController', OtherController)
.directive('contactCard', contactCard)
.factory('cacheFactory', cacheFactory)
.factory('httpInterceptor', httpInterceptor);
}());
.container-fluid {
background-color: #222;
color: #fff;
aside {
position: absolute;
left: 1px;
top: 5px;
ul {
list-style-type: none;
padding: 10px;
li {
margin: 0 0 4px 4px;
}
li a {
padding: 4px;
text-decoration: none;
color: #fff;
}
.active {
background-color: #fff;
color: #222;
border-radius: 4px;
}
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.3.1/angular-ui-router.js"></script>
<div class="container-fluid" ng-app="app">
<aside>
<ul>
<li><a ui-sref="home" ui-sref-active="active">Home</a>
</li>
<li><a ui-sref="other" ui-sref-active="active">Other</a>
</li>
</ul>
</aside>
<div class="container" ui-view>
<h1 class="text-center" ng-bind="vm.title"></h1>
</div>
</div>

ngAnimate causes element.css ('display','block') failure when reloading the route

This example is injected into the ngAnimate.
First, you need to visit this test page like "/#/test/1" , 3 seconds after the modified $location.path ('/test/2'), the controller is re loaded,but the floating layer can not be displayed (box.css('display', 'block') failure).
If you do not inject ngAnimate, everythings is ok, the floating layer can be displayed.
I don't know what's going on, it's a bug ngAnimate?
HTML:
<!doctype html>
<html ng-app="app">
<head>
<meta charset="utf-8">
<title>test</title>
<style type="text/css">
.popup {
position: fixed; width: 100%; height: 100%; background-color: rgba(36,36,36,.96); top: 0; left: 0; z-index: 1;
}
.popup .context .hd {
font-size: 32px; color:#FFF; text-align: center;
}
.popup .close {
font-size: 32px; color:#999; text-align: center;
}
</style>
</head>
<body>
<div class="wrapper" ng-view></div>
<script src="angular_1.4.1.min.js" type="text/javascript"></script>
<script src="angular-route.min.js" type="text/javascript"></script>
<script src="angular-animate.min.js" type="text/javascript"></script>
</body>
</html>
template demo.html
route : <span style="color:red; font-size: 32px;">{{id}}</span>
<input type="button" pop-window-open ng-click="openPopWindow()" style="width:200px; height: 50px;" value="open window">
<section class="popup" id="popWindow" style="display: none;">
<div class="context">
<div class="hd">pop window</div>
<div class="bd"></div>
</div>
<div class="close" pop-window-close ng-click="closePopWindow()">close</div>
</section>
javascript:
angular.module('app', ['ngRoute', 'ngAnimate', 'youyuApp.controllers', 'youyuApp.directives'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/test/:id', {
templateUrl : 'demo.html',
controller : 'ctrl1'
});
}]);
angular.module('youyuApp.controllers', [])
.controller('ctrl1', ['$scope', '$location', '$timeout', '$routeParams',
function($scope, $location, $timeout, $routeParams) {
$scope.id = $routeParams.id;
$timeout(function() {
$location.path('/test/2');
}, 3000);
}]);
angular.module('youyuApp.directives', [])
.directive('popWindowOpen', function() {
return {
restrict: 'EA',
link : function(scope, element, attrs) {
var box = angular.element(document.getElementById('popWindow'));
scope.openPopWindow = function() {
box.css('display', 'block');
};
}
}
})
.directive('popWindowClose', function() {
return {
restrict: 'EA',
scope : true,
link : function(scope, element, attrs) {
var box = angular.element(document.getElementById('popWindow'));
scope.closePopWindow = function() {
box.css('display', 'none');
};
}
}
})

latest 1.1.5 ng-animate not working with ng-show

The following code is adopted from a working sample for angular 1.1.4, only using the new GreenSock api for ng-animate. toggle functionality works, as ng-show behaves as expected, however The AppAnimation functions 'list-in' and 'list-out' are not being called on ng-show.
<!DOCTYPE html>
<head>
<style>
.box { color: white; text-align: center; height: 100px; font-size: 86px; }
.on { background-color: green; }
.off { background-color: red; }
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/gsap/1.9.7/TweenMax.min.js"></script>
<script>
angular.module('AppAnimations', [])
.animation('list-out', ['$window',function($window) {
return {
start : function(element, done) {
console.log('list-out')
TweenMax.set(element, {position:'relative'});
var duration = 1;
//we can use onComplete:done with TweenMax, but lets use
//a delay value for testing purposes
TweenMax.to(element, 1, {opacity:0, width:0});
$window.setTimeout(done, duration * 1000);
}
}
}])
.animation('list-in', ['$window',function($window) {
return {
setup: function(element) {
TweenMax.set(element, {opacity:0, width:0});
},
start : function(element, done) {
console.log('list-in')
var duration = 1;
//we can use onComplete:done with TweenMax, but lets use
//a delay value for testing purposes
TweenMax.to(element, duration, {opacity:1, width:210});
$window.setTimeout(done, duration * 1000);
}
}
}])
angular.module('myApp', ['AppAnimations'])
.controller('MainController', ['$scope', function($scope) {
$scope.toggle = true;
}])
</script>
</head>
<body ng-app="myApp" ng-controller="MainController">
<button ng-click="toggle = !toggle">Toggle!</button>
<div class="box on" ng-show="toggle" ng-animate="{leave:'list-out', enter:'list-in'}">On</div>
<div class="box off" ng-hide="toggle" ng-animate="{leave:'list-out', enter:'list-in'}">Off</div>
</body>
</html>
<div class="box on" ng-show="toggle" ng-animate="{show: 'list-in', hide: 'list-out'}">On</div>
<div class="box off" ng-hide="toggle" ng-animate="{show: 'list-in', hide: 'list-out'}">Off</div>
So I finally solved it.. you are using leave/enter and should be using show/hide. I updated the names to be more PC correct.
<div class="box on" ng-show="toggle" ng-animate="{hide:'list-hide', show:'list-show'}">On</div>
<div class="box off" ng-hide="toggle" ng-animate="{hide:'list-hide', show:'list-show'}">Off</div>
angular.module('AppAnimations', [])
.animation('list-hide', ['$window',function($window) {
...
).animation('list-show', ['$window',function($window) {
Working fiddle: http://jsfiddle.net/ncapito/CTfL8/

Resources