Django template not rendering JSON response when used with AngularJS - angularjs

EDIT: Solved
views.py
def post_list(request):
queryset = Post.objects.all()
json_data = serializers.serialize('json', queryset)
context = {
"jsondata" : json_data,
}
return render(request,"index.html", context)
index.html
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/1.11.8/semantic.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body ng-app="myapp" ng-controller="myctrl">
{{ jsondata }}
<div class="ui icon input">
<input type="text" ng-model="search" placeholder="Search skills...">
<i class="search link icon"></i>
</div>
<div class="ui link cards" style="padding:40px">
<div class="card">
<div class="image">
<img class="ui avatar centered image" src="http://1.semantic-ui.com/images/avatar/large/elliot.jpg">
</div>
<div class="content">
<div class="ui small header" ng-repeat="skill in skills | filter:search">
{{ skill.fields.post_title}}
</div>
<div class="description">
{{ skill.fields.post_content }}
</div>
</div>
</div>
</div>
<script type="text/javascript">
var skills_list = "{{ jsondata }}";
var nice_data = JSON.parse(skills_list.replace(/"/g, '"'))
var very_nice_data = JSON.stringify(nice_data);
console.log(very_nice_data)
</script>
<script>
angular.module('skillboard', []).controller('searchskills', function ($scope) {
$scope.skills = very_nice_data;
});
</script>
</body>
Output of **very_nice_data** in console is:
[
{
"model": "posts.post",
"pk": 1,
"fields": {
"post_title": "Algorithms",
"post_content": "Calling it.",
"updated_on": "2016-06-12T09:09:45.198Z",
"timestamp": "2016-04-20T09:44:21.887Z",
"test_type": "Coding",
"number_of_questions": 0,
"test_url": "http://example.com"
}
},
{
"model": "posts.post",
"pk": 4,
"fields": {
"post_title": "Data Structures",
"post_content": "new content here",
"updated_on": "2016-06-12T09:09:26.359Z",
"timestamp": "2016-04-26T06:28:32.569Z",
"test_type": "Coding",
"number_of_questions": 0,
"test_url": "http://example.com"
}
},
{
"model": "posts.post",
"pk": 11,
"fields": {
"post_title": "Dynamic Programming",
"post_content": "This level of DP is well suited for 2+ yr experience programmers/researchers.",
"updated_on": "2016-06-12T09:09:16.542Z",
"timestamp": "2016-06-12T08:44:25.705Z",
"test_type": "Coding",
"number_of_questions": 0,
"test_url": "#"
}
}
]
I am trying to render JSON response from my django view into my template using angular. I am using semantic cards for each item. JSON response is perfectly fine. ng-repeat is also looping for number of items in the JSON but post_title and post_content is not displaying.
<div class="ui small header" ng-repeat="skill in skills | filter:search">
{{ skill.fields.post_title }}
</div>
<div class="description">
{{ skill.fields.post_content }}
</div>
Where is the bug? Please help.

Don't stringify very-nice_data.
It needs to be a javscript array not a json string when you do $scope.skills = very_nice_data;

What Charlieftl answered is perfect. Instead of var very_nice_data = JSON.stringify(nice_data); just do var very_nice_data = nice_data;
var app = angular.module("skillboard", []);
app.controller("searchskills", function($scope) {
$scope.skills = very_nice_data;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="skillboard" ng-controller="searchskills">
<div class="ui small header" ng-repeat="skill in skills | filter:search">
{{ skill.fields.post_title }}
</div>
</div>
<script type="text/javascript">
var skills_list = '[{"model":"posts.post","pk":1,"fields":{"post_title":"Algorithms","post_content":"Calling it.","updated_on":"2016-06-12T09:09:45.198Z","timestamp":"2016-04-20T09:44:21.887Z","test_type":"Coding","number_of_questions":0,"test_url":"http://example.com"}},{"model":"posts.post","pk":4,"fields":{"post_title":"Data Structures","post_content":"new content here","updated_on":"2016-06-12T09:09:26.359Z","timestamp":"2016-04-26T06:28:32.569Z","test_type":"Coding","number_of_questions":0,"test_url":"http://example.com"}},{"model":"posts.post","pk":11,"fields":{"post_title":"Dynamic Programming","post_content":"This level of DP is well suited for 2+ yr experience programmers/researchers.","updated_on":"2016-06-12T09:09:16.542Z","timestamp":"2016-06-12T08:44:25.705Z","test_type":"Coding","number_of_questions":0,"test_url":"#"}}]'
var nice_data = JSON.parse(skills_list.replace(/"/g, '"'))
var very_nice_data = nice_data;
</script>

Finally resolve the issue. I encountered to issue below:
There was conflict in the curly braces of django and angular view bindings. So i created custom bindings below.
var app=angular.module('appName', []);
app.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('[[');
$interpolateProvider.endSymbol(']]');
});

Related

best practice and performance in angularJS ng-if with class and icon

2 options:
what is better for performance and watchers using, now I am using the first option and I would like to improve performance
the object today looks like:
message = {
message : X,
}
and I would like to do somthing like :
obj = {
text : text,
icon: "src.png"
status: X,
class : "className",
color: "color_code_like_#ffff"
}
1 :
<div ng-if="message.message == 0" class="classA" style="">
<span class="same"><img class="sameClass" ng-src="a.gif"></span>
<span class="status-text a_with_animation" style="color:red;">textA</span>
</div>
<div ng-if="message.message == 1" class="classB" style="">
<span class="same"><img class="sameClass" ng-src="b.png"></span>
<span class="status-text" style="color:blue;">textB</span>
</div>1
<div ng-if="message.message == 2" class="classC" style="">
<span class="same"><img class="sameClass" ng-src="c.png"></span>
<span class="status-text" style="color:black;">TextC</span>
</div>
option 2
<div class="{{obj.class}}" style="">
<span class="same"><img class="sameClass" ng-src="{{obj.class}}"></span>
<span class="status-text {{obj.animation}" style="color:red;">
{{obj.text}}</span>
</div>
also all the data here is two way binding
Not really pretty but I made an example of how you could populate your data with ng-include template. Here is a demo:
<!DOCTYPE html>
<html ng-app="myApp">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-controller="myCtrl">
<select ng-model="message" ng-change="change()" ng-options="x.message for x in messages">
</select>
<br>
ngInclude: <div ng-include="'abc.html'"></div>
Directive: <div temp-directive></div>
<!-- A separate file for the template -->
<script type="text/ng-template" id="abc.html">
<div class="{{obj.class}}" style="">
<span class="same"><img class="sameClass" ng-src="{{obj.icon}}"></span>
<span class="status-text {{obj.animation}}" ng-style="obj.style">
{{obj.text}}</span>
</div>
</script>
</div>
<script>
var app = angular.module('myApp', []);
app.directive("tempDirective", function() {
return {
template : "<div class='{{obj.class}}' style=''><span class='same'><img class='sameClass' ng-src='{{obj.icon}}'></span><span class='status-text {{obj.animation}}' ng-style='obj.style'> {{obj.text}}</span></div>"
};
});
app.controller('myCtrl', function($scope) {
$scope.messages = [{
"message": 0
}, {
"message": 1
}, {
"message": 2
}];
$scope.message = $scope.messages[0]; // initialise
$scope.objects = [{
"text": "Message - 0",
"icon": "a.gif",
"animation": "a_with_animation",
"class": "classA",
"style": {
"color": "#00aaaa"
}
}, {
"text": "Message - 1",
"icon": "b.png",
"animation": "",
"class": "classB",
"style": {
"color": "#aa00aa"
}
}, {
"text": "Message - 2",
"icon": "c.png",
"animation": "",
"class": "classC",
"style": {
"color": "#aaaa00"
}
}];
$scope.obj = $scope.objects[0]; // initialise
$scope.change = function() { // changing the template data
$scope.obj = $scope.objects[$scope.message.message];
}
});
</script>
</body>
</html>
[Note]: it is best to replace ng-include with a component / directive with their template (not templateUrl) for performance improvement, since it is asynchronous and takes time to load the HTML

angular ng-repeat array show only one element

I have an array like this
$scope.mentors = [ {"name":"Jonathan", "status":0},
{"name": "Nathan","status":1},
{"name": "Chris","status":1},
{"name": "Brian","status":0}];
here my view code
<div ng-repeat="m in mentors">
<div ng-if="m.status == '1'">
<div>
{{m.name}}
</div>
</div>
</div>
and my result is :
Nathan and Chris
what can I do to just make it show Nathan or Chris
it must only show one result only
p/s: already try ng-show="$last" it did not work since Brian status is '0'
You can filter the array on statuses and then just take the first by checking against $index
angular.module('app', []).controller('myCtrl',function($scope){
$scope.mentors = [ {"name":"Jonathan", "status":0},
{"name": "Nathan","status":1},
{"name": "Chris","status":1},
{"name": "Brian","status":0}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html>
<body ng-app="app">
<div ng-controller="myCtrl">
<div ng-repeat="m in mentors | filter : {status: 1}">
<div ng-if="$index == 0">
<div>
{{m.name}}
</div>
</div>
</div>
</div>
</body>
</html>
You could use the limitTo and filter
<div ng-repeat="m in mentors | filter: { status : '1'}| limitTo : 1">
<div>
{{m.name}}
</div>
</div>
There is no reason to use ng-repeat if you only need to display 1 item.
You should handle this in your controller. Create a new variable that will hold the mentor that you want to show.
To find Nathan, you can use Array#find(). It will return the first item that matches the condition status === 1
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.mentors = [{
"name": "Jonathan",
"status": 0
},
{
"name": "Nathan",
"status": 1
},
{
"name": "Chris",
"status": 1
},
{
"name": "Brian",
"status": 0
}
];
$scope.mentor = $scope.mentors.find(m => m.status === 1);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<h1>{{mentor.name}}</h1>
</div>

ng-repeat not listing different json values, instead it just displays the entire json file content in single list item

ng-repeat is not listing different json values, instead it just displays the entire json file content in single list item
codepen
html:
<div ng-app="myApp">
<div ng-controller="myCtrl" class="container">
<h2>Basic List</h2>
<ul class="list-group">
<li class="list-group-item" ng-reapeat="student">
{{student}}
</li>
</ul>
</div>
</div>
All the json file content is in here. I just need the specific data to display on each list item.
For Example,
Student One
Student Two
Student Three
Student Four
Student Five
See image for issue
JS
<script>
var app = angular.module('myApp', []);
//$.ajax({url: app, crossDomain:true, dataType: 'json', type: 'GET'})
app.controller('myCtrl', function($scope, $http){
$http.get("student.json")
// $http.get("stud.json")
.then(function(response) {
$scope.student = response.data;
});
});
</script>
json
[
{
"name" : "Student One"
},
{
"name" : "Student Two"
},
{
"name" : "Student Three"
},
{
"name" : "Student Four"
},
{
"name" : "Student Five"
}
]
Your ng-repeat should be look like, to be more on that, you are missing the proper syntax and its ng-repeat not ng-reapeat
<li class="list-group-item" ng-repeat="stu in student" >
{{stu.name}}
</li>
DEMO
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.student =
[
{
"name": "Student One"
},
{
"name": "Student Two"
},
{
"name": "Student Three"
},
{
"name": "Student Four"
},
{
"name": "Student Five"
}
];
});
<!DOCTYPE html>
<html>
<head>
</head>
<body >
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl" >
<div class="container">
<h2>Basic List</h2>
<ul class="list-group">
<li ng-repeat="stu in student" >
{{stu.name}}
</li>
</ul>
</div>
</div>
</body>
I figured it out!
I fixed the syntax of the parameter in ng-repeat attribute.
So instead of the previous :
<ul class="list-group">
<li class="list-group-item" ng-reapeat="student">
{{student}}
</li>
Before
it should be like this :
<ul class="list-group" >
<li class="list-group-item" ng-repeat="student in student" >
{{student.name}}
</li>
Result:
After

Angularjs: how to pass $filter to function in case of "controller as" syntax?

I am new to AngularJS. I am trying to work out an example of a SportsStore app from a book I am following.
In this app, there are several categories of products. Categories are also displayed on the left side of the view.
Clicking a "category" is going to filter the products by category and is going to highlight the Category button.
Reading tutorials on net I understand that the "controller as" syntax is being favored over the "$scope" syntax.
How do I pass a filter (categoryFilterFn) to my controller function for filtering the products by category?
app.html
<!DOCTYPE html>
<html ng-app="SportsStoreApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular-resource.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.css" rel="stylesheet" />
<script src='app.js'></script>
<script src='customFilters.js'></script>
<script src='productListControllers.js'></script>
</head>
<body ng-controller="SportsStoreCtrl as controller">
<div class="navbar navbar-inverse">
<a class="navbar-brand" href="#">SPORTS STORE</a>
</div>
<div class="panel panel-default row" ng-controller="ProductListCtrl">
<div class="col-xs-3">
<a ng-click="selectCategory()"
class="btn btn-block btn-default btn-lg">Home</a>
<a ng-repeat="item in controller.data.products | orderBy:'category' | unique_selection:'category'"
ng-click="selectCategory(item)" class=" btn btn-block btn-default btn-lg"
ng-class="getCategoryClass(item)">
{{item}}
</a>
</div>
<div class="col-xs-8">
<div class="well" ng-repeat="item in controller.data.products | filter:categoryFilterFn">
<h3>
<strong>{{item.name}}</strong>
<span class="pull-right label label-primary">
{{item.price | currency}}
</span>
</h3>
<span class="lead">{{item.description}}</span>
</div>
</div>
</div>
</body>
</html>
customFilters.js
angular.module("customFilters", [])
.filter("unique_selection", function(){
return function(data, propertyName) {
if (angular.isArray(data) && angular.isString(propertyName)) {
var results = [];
var keys = {};
for (var i = 0; i < data.length; i++) {
var val = data[i][propertyName];
if (angular.isUndefined(keys[val])) {
keys[val] = true;
results.push(val);
}
}
return results;
} else {
return data;
}
}
});
app.js
var app = angular.module("SportsStoreApp", ['customFilters']);
app.controller("SportsStoreCtrl", function(){
this.data = {
products: [
{ name: "Product #1", description: "A product",
category: "Category #1", price: 100 },
{ name: "Product #2", description: "A product",
category: "Category #1", price: 110 },
{ name: "Product #3", description: "A product",
category: "Category #2", price: 210 },
{ name: "Product #4", description: "A product",
category: "Category #3", price: 202 }
]
};
});
productListControllers.js
angular.module("SportsStoreApp")
.constant('productListActiveClass', "btn-primary")
.controller('ProductListCtrl', function($scope, $filter, productListActiveClass) {
var selectedCategory = null;
$scope.selectCategory = function(newCategory) {
selectedCategory = newCategory;
};
$scope.categoryFilterFn = function(product) {
return selectedCategory == null ||
product.category == selectedCategory;
};
$scope.getCategoryClass = function(category) {
return selectedCategory = category ? productListActiveClass : "";
};
});
In productListControllers.js, how do I not use "$scope" object and use "this" object along with "$filter" argument? Also, how can I use "ProductListCtrl as product_ctrl" in app.html?
If you want to use your custom filter inside a controller, simply inject your custom filter into your controller using the name of your filter and the suffix Filter.
In your instance you need to inject unique_selectionFilter. You can then use it in your controller passing in your data and property name values:
unique_selectionFilter(data, propertyName)
Alternatively you can inject the $filter service and access your filter through it by passing in it's name:
$filter('unique_selection')(data, propertyName)

AngularJS ng-repeat filtering JSON error

I'm learning about AngularJS and I have an error in Chrome console when I do this:
<input ng-model="search" />
<ul>
<li ng-repeat="prof in profesores | filter:search">
{{prof.nombre}} - {{prof.telefono}}
</li>
</ul>
with this data "profesores":
{
"profesores": [
{
"id": 0,
"sexo": "hombre",
"nombre": "Kari",
"snombre": "Carr",
"telefono": "(826) 453-3497",
"celular": "(801) 9175-8136"
},
{
"id": 1,
"sexo": "mujer",
"nombre": "Tameka",
"snombre": "Gamble",
"telefono": "(824) 438-2499",
"celular": "(801) 8595-8337"
} ]
}
The error is this:
The code works correctly (filter the items with string in input) but I have the error in console. What am I doing wrong?
Here ng-repeat="prof in profesores | search" --> wrong
ng-repeat="prof in profesores |filter: search" --> right
var myApp = angular.module('myApp',[]);
myApp.controller('samplecontroller', function($scope) {
$scope.profesores = [
{
"id": 0,
"sexo": "hombre",
"nombre": "Kari",
"snombre": "Carr",
"telefono": "(826) 453-3497",
"celular": "(801) 9175-8136"
},
{
"id": 1,
"sexo": "mujer",
"nombre": "Tameka",
"snombre": "Gamble",
"telefono": "(824) 438-2499",
"celular": "(801) 8595-8337"
}
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!doctype html>
<html >
<head>
</head>
<body ng-app="myApp">
<div ng-controller="samplecontroller">
<input ng-model="search" />
<ul>
<li ng-repeat="prof in profesores |filter: search">
{{prof.nombre}} - {{prof.telefono}}
</li>
</ul>
</div>
</body>
</html>
Initialiae it with an empty array like this when js loads:
$scope.profesores = []
Then you can define the variable again in your promise :
$http.get('json/profesores.json') .success(function(data){ $scope.profesores = data.profesores; });
Until the data is loaded from the server your profesores variable is undefined and will throw the error. Initialize it with an empty array at the beginning o your controller:
$scope.profesores = [];
After that you can request the data and fill the array:
$http.get('json/profesores.json').success(function(response){
$scope.profesores = response.profesores;
});

Resources