Reputation: 33
I've been following this tutorial here for the infinite scrolling.
http://en.proft.me/2015/09/4/how-make-infinity-scroll-loading-bar-angularjs/
but for some reason it's throwing me this error
"angular.js:38Uncaught Error: [$injector:modulerr"
am i doing something wrong here?
im a newbie to django rest framework and angular js.
what i want to achieve here is having the API json data loaded and injected into the html (which i did) and have it scrollable and clickable. (with hyperlinks, but without refreshing the page)
could anyone take a look at the code?
index.html
<body>
<div class="pinGridWrapper" ng-app="PinApp" ng-controller="PinCtrl">
<div class="pinGrid" infinite-scroll='pins.more()' infinite-scroll-disabled='pins.busy' infinite-scroll-distance='1'>
<div class="pin" ng-repeat="pin in pins.items">
<img ng-src="{$ pin.photo $}">
<div ng-app="myApp" class="app">
<div ng-controller="appCtrl as vm" class="main-container">
<h1>Post List</h1>
{% verbatim %}
<div ng-repeat="post in vm.posts | limitTo: 10" class="post">
<a href="{{ post.url}}">
<h2>{{ post.title }}</h2>
<p>{{ post.content }}</p>
</a>
<p ng-if="vm.loadingPosts">Loading...</p>
</div>
{% endverbatim %}
</div>
</div>
<p ng-bind-html="pin.text"></p>
</div>
</div>
<div ng-show='pins.busy'><i class="fa fa-spinner"></i></div>
</div>
<!-- Latest compiled and minified JavaScript -->
<script src="http://code.jquery.com/jquery-1.12.2.min.js" integrity="sha256-lZFHibXzMHo3GGeehn1hudTAP3Sc0uKXBXAzHX1sjtk=" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-animate.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-route.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.5/marked.min.js'></script>
<script>
/* ng-infinite-scroll - v1.0.0 - 2013-02-23 */
var mod;mod=angular.module("infinite-scroll",[]),mod.directive("infiniteScroll",["$rootScope","$window","$timeout",function(i,n,e){return{link:function(t,l,o){var r,c,f,a;return n=angular.element(n),f=0,null!=o.infiniteScrollDistance&&t.$watch(o.infiniteScrollDistance,function(i){return f=parseInt(i,10)}),a=!0,r=!1,null!=o.infiniteScrollDisabled&&t.$watch(o.infiniteScrollDisabled,function(i){return a=!i,a&&r?(r=!1,c()):void 0}),c=function(){var e,c,u,d;return d=n.height()+n.scrollTop(),e=l.offset().top+l.height(),c=e-d,u=n.height()*f>=c,u&&a?i.$$phase?t.$eval(o.infiniteScroll):t.$apply(o.infiniteScroll):u?r=!0:void 0},n.on("scroll",c),t.$on("$destroy",function(){return n.off("scroll",c)}),e(function(){return o.infiniteScrollImmediateCheck?t.$eval(o.infiniteScrollImmediateCheck)?c():void 0:c()},0)}}}]);
var app = angular.module('PinApp', ['ngAnimate', 'ngSanitize', 'ngResource', 'infinite-scroll']);
app.config(function($interpolateProvider, $httpProvider, cfpLoadingBarProvider) {
$interpolateProvider.startSymbol('{$');
$interpolateProvider.endSymbol('$}');
cfpLoadingBarProvider.includeSpinner = false;
});
app.factory('Pin', function($http, cfpLoadingBar){
var Pin = function() {
this.items = [];
this.busy = false;
this.url = "/api/posts/?limit=2&offset=0";
}
Pin.prototype.more = function() {
if (this.busy) return;
if (this.url) {
this.busy = true;
cfpLoadingBar.start();
$http.get(this.url).success(function(data) {
var items = data.results;
for (var i = 0; i < items.length; i++) {
this.items.push(items[i]);
}
this.url = data.next;
this.busy = false;
cfpLoadingBar.complete();
}.bind(this));
}
};
return Pin;
})
app.controller('PinCtrl', function($scope, Pin){
$scope.pins = new Pin();
$scope.pins.more();
});
</script>
urls.py
from django.conf.urls import url
from django.contrib import admin
from .views import (
PostListAPIView,
PostDetailAPIView,
PostUpdateAPIView,
PostDeleteAPIView,
PostCreateAPIView,
)
from django.conf.urls import patterns, url, include
from .views import PostListView
urlpatterns = [
url(r'^$', PostListAPIView.as_view(), name='list'),
url(r'^create/$', PostCreateAPIView.as_view(), name='create'),
#url(r'^create/$', post_create),
url(r'^(?P<slug>[\w-]+)/$', PostDetailAPIView.as_view(), name='detail'),
url(r'^(?P<slug>[\w-]+)/edit/$', PostUpdateAPIView.as_view(), name='update'),
url(r'^(?P<slug>[\w-]+)/delete/$', PostDetailAPIView.as_view(), name='delete'),
#url(r'^(?P<slug>[\w-]+)/edit/$', post_update, name ='update'),
#url(r'^(?P<slug>[\w-]+)/delete/$', post_delete),
#url(r'^posts/$', "<appname>.views.<function_name>"),
url(r'^$', PostListView.as_view(), name='list2')
]
serializers.py
from rest_framework.serializers import ModelSerializer, HyperlinkedIdentityField
from posts.models import Post
class PostCreateUpdateSerializer(ModelSerializer):
class Meta:
model = Post
fields = [
#'id',
'title',
#'slug',
'content',
'publish'
]
class PostDetailSerializer(ModelSerializer):
class Meta:
model = Post
fields = [
'id',
'title',
'slug',
'content',
'publish'
]
class PostListSerializer(ModelSerializer):
url = HyperlinkedIdentityField(
view_name='posts-api:detail',
lookup_field='slug'
)
delete_url = HyperlinkedIdentityField(
view_name='posts-api:delete',
lookup_field='slug'
)
class Meta:
model = Post
fields = [
'url',
'id',
'title',
'content',
'publish',
'delete_url'
]
from rest_framework import serializers
class PinSerializer(serializers.ModelSerializer):
class Meta:
model = Post
views.py
from rest_framework.generics import CreateAPIView, ListAPIView, RetrieveAPIView, UpdateAPIView, DestroyAPIView
from posts.models import Post
from .serializers import PostCreateUpdateSerializer, PostListSerializer, PostDetailSerializer
from rest_framework.pagination import LimitOffsetPagination, PageNumberPagination
from .pagination import PostLimitOffsetPagination, PostPageNumberPagination
class PostCreateAPIView(CreateAPIView):
queryset = Post.objects.all()
serializer_class = PostCreateUpdateSerializer
class PostDetailAPIView(RetrieveAPIView):
queryset = Post.objects.all()
serializer_class = PostDetailSerializer
lookup_field = 'slug'
class PostUpdateAPIView(UpdateAPIView):
queryset = Post.objects.all()
serializer_class = PostCreateUpdateSerializer
lookup_field = 'slug'
class PostDeleteAPIView(DestroyAPIView):
queryset = Post.objects.all()
serializer_class = PostDetailSerializer
lookup_field = 'slug'
class PostListAPIView(ListAPIView):
queryset = Post.objects.all()
serializer_class = PostListSerializer
# pagination_class = PostLimitOffsetPagination
from rest_framework import generics
from rest_framework import filters
from rest_framework.pagination import LimitOffsetPagination
from .serializers import PostListSerializer
class PostListView(generics.ListAPIView):
queryset = Post.objects.all()
serializer_class = PostListSerializer
filter_backends = (filters.DjangoFilterBackend,)
filter_fields = ('category',)
pagination_class = LimitOffsetPagination
thanks.
the live site is here : http://192.241.153.25:8000/
Upvotes: 0
Views: 655
Reputation: 3363
Your first error was the missing sanitize module as I referenced in my comment. Adding the missing include:
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-sanitize.js"></script>
Will fix that.
Your current error is really a new question but has to do with this code in your index page (line 498 of the rendered index page).
$http.get(this.url).success(function(data) {
var items = data.results;
for (var i = 0; i < items.length; i++) {
this.items.push(items[i]);
}
...
The data object that your code is being returned looks like this:
[ { "url":"http://192.241.153.25:8000/api/posts/test-2/", "id":3, "title":"test", "content":"test", "publish":"2016-01-01", "delete_url":"http://192.241.153.25:8000/api/posts/test-2/delete/" }, ... ]
It doesn't have a results property. I didn't really look into what you were doing with it but you probably want this (notice the lack of the "results"):
$http.get(this.url).success(function(data) {
var items = data;
for (var i = 0; i < items.length; i++) {
this.items.push(items[i]);
}
...
Or you want to change up what you're returning so that it has a results property.
Upvotes: 1
Reputation: 113988
<div ng-app="myApp" class="app">
<div ng-controller="appCtrl as vm" class="main-container">
<h1>Post List</h1>
{% verbatim %}
<div ng-repeat="post in vm.posts | limitTo: 10" class="post">
<a href="{{ post.url}}">
<h2>{{ post.title }}</h2> <!-- this is django template language and expects a django context variable named post that has an attribute of title -->
<p>{{ post.content }}</p>
</a>
<p ng-if="vm.loadingPosts">Loading...</p>
</div>
{% endverbatim %}
</div>
</div>
instead you must escape your {{
and }}
for angular to see them
{% templatetag openvariable %} angular_variable {% templatetag closevariable %}
or use something like https://github.com/jrief/django-angular
Upvotes: 0