Hey I have one question about pagination. This code is useful when I load data from database e.g. list of users. But now I want to dynamically create inputs (for quiz questions) and use $index in ng-repeat.
There's a problem, however: because I use slice in pagination, $index is sliced too. In my example there are two items on the page, but if you create more than two you'll see the same numbers - 'Question 1' and 'Question 2' on all the pages.
How I can correctly set up $index in pagination? I would like that on first page will be 1,2 on second 3,4 etc.
angular.module('myApp', ['ui.bootstrap'])
.controller('myCtrl', function($scope){
$scope.currentPage = 2;
$scope.itemsPerPage = 2;
$scope.questionQuiz = [];
$scope.addQuizQuestion = function(){
$scope.questionQuiz.push({});
$scope.totalItems = $scope.questionQuiz.length;
}
})
a:hover
{
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet">
<body ng-app="myApp" ng-controller="myCtrl">
<a class="input-group-addon" ng-click="addQuizQuestion()">
<i class="fa fa-plus"></i> Add question
</a>
<div ng-repeat="question in questionQuiz.slice(((currentPage-1)*itemsPerPage), ((currentPage*itemsPerPage))) track by $index">
<label><h3>Question {{$index + 1}}</h3></label>
<input type="text" ng-model="input[$index]" class="form-control" placeholder="Write something...">
</div>
<pagination total-items="totalItems" ng-model="currentPage" class="pagination-sm text-center" items-per-page="itemsPerPage" previous-text="Prev" next-text="Next"> </pagination>
</body>
Just add the number of items before the indexed one, like this:
<label><h3>Question {{$index + 1 + (currentPage - 1) * itemsPerPage}}</h3></label>
Related
I'm having trouble trying to figure out how to fix a bug that happens when I try to push the same string as added previously to the array. It gets stuck and will not allow the app to post another string.
How do I make sure that your repeat doesn't get stuck when there two of the same values in the array?
Bug Example Screenshot
--> Bug happens when I try to push "1"into the array again after a "1" is already posted.
HTML Code
<body>
<div data-ng-controller="appController" class="container">
<div class="row">
<form>
<label for = "status"> Status: </label>
<input data-ng-model = "input_data" type="text" id="status"/>
<button data-ng-click="add_data()"> OK </button>
<ul class = "list-group">
<li class="list-group-item" data-ng-repeat="x in array_data">
{{x}}
<button data-ng-click = "remove_data($index)">DEL</button>
</li>
</ul>
</form>
</div>
</div>
<script src="framework/js/jquery.min.js"></script>
<!-- All Bootstrap plug-ins file -->
<script src="framework/js/bootstrap.min.js"></script>
<!-- Basic AngularJS -->
<script src="framework/js/angular.min.js"></script>
<!-- Your Controller -->
<script src="framework/js/appstatpost.js"></script>
</body>
AngularJS code
var app = angular.module("myApp", []);
app.controller("appController", function ($scope) {
$scope.array_data = [];
$scope.add_data = function () {
$scope.array_data.push($scope.input_data);
};
$scope.remove_data = function (index) {
$scope.array_data.splice(index, 1);
};
});
You could use track by $index, example:
<li class="list-group-item" data-ng-repeat="x in array_data track by $index">
AngularJS tries by default to find a key in your array to index by. Normally this works well, but if you have duplicates then you have to tell AngularJS to make a new index, in this case, $index.
ng-repeat is binding same array with multiple times.
js :
$scope.currentitem = item;
$scope.currentitemCategory = $scope.currentitem.category.split(',');
console.log($scope.currentitemCategory);
html:
<div ng-repeat="category in currentitemCategory track by $index">
<a href="/content/digital-library/us/en/search.html?category={{category}}">
<span class="text"> {{category}} </span>
</a>
</div>
console :
Categorized in
audience/business
audience/business
audience/business
brandguidelines
brandguidelines
brandguidelines
corporateinitiatives/idf
corporateinitiatives/idf
corporateinitiatives/idf
I've created a sample application with your given snippet. I do not see any repeated entries. Everything works fine. Please provide few more details if the issue really exists.
var app= angular.module('sample', []);
app.controller('samplecontroller', function($scope){
var item = {category: 'Tennis, Carroms, Soccer, Volleyball'};
$scope.currentitem = item;
$scope.currentitemCategory = $scope.currentitem.category.split(',');
console.log($scope.currentitemCategory);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="sample">
<div ng-controller="samplecontroller">
<div ng-repeat="category in currentitemCategory track by $index">
<a href="/content/digital-library/us/en/search.html?category={{category}}">
<span class="text"> {{category}} </span>
</a>
</div>
</div>
</body>
I currently have this site - http://dev.5874.co.uk/scd-data/ where I have a dropdown which displays results from WP-API which I am pulling in through AngularJS.
It currently combines the two sets of results as they're separate URL's, the results are in categories within a custom post type so if both posts are 'tagged' in the same category chosen they display twice. I need a way to combine the two sets of results but only showing one of the posts - I hope this makes sense. I'm very new to API data and AngularJS and I imagine there is a much simpler way of doing this. Any help would be much appreciated. Here is a snippet of my code to show how it's currently working.
Thanks in advance!
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
<style>
.desc {display: none;}
</style>
<script type="text/javascript">
$(function(){
$('.selectOption').change(function(){
var selected = $(this).find(':selected').text();
//alert(selected);
$(".desc").hide();
$('#' + selected).show();
}).change()
});
</script>
<script>
var app = angular.module('myApp', []);
app.controller('northWestCtrl', function($scope, $http) {
var url = 'http://scd.blaze.wpengine.com/wp-json/posts?type=listings&filter[listing_area]=northwest';
$http.get(url).then(function(data) {
$scope.data = data.data;
});
});
</script>
<select class="selectOption">
<option>Search by Region</option>
<option>NorthWest</option>
<option>NorthEast</option>
<option>Midlands</option>
<option>EastAnglia</option>
<option>SouthEast</option>
<option>SouthWest</option>
<option>Scotland</option>
<option>Wales</option>
<option>NorthernIreland</option>
<option>ChannelIslands</option>
</select>
<div id="changingArea">
<body ng-app="myApp">
<div id="NorthWest" class="desc">
<div ng-controller="northWestCtrl">
<div ng-repeat="d in data">
<h2 class="entry-title title-post">{{d.title}}</h2>
<img src="{{d.acf.logo}}">
<div id="listing-contact">Contact: {{d.acf.contact}}, {{d.acf.position}}</div>
<div id="listing-address-1">
{{d.acf.address_1}}, {{d.acf.address_2}} {{d.acf.address_3}} {{d.acf.town}} {{d.acf.county}} {{d.acf.postcode}}
</div>
<div id="listing-phone">Telephone: {{d.acf.telephone}}</div>
<div id="listing-mobile">Mobile: {{d.acf.mobile}}</div>
<div id="listing-email">Email: {{d.acf.email}}</div>
<div id="listing-website">Website: {{d.acf.website}}</div>
<div id="listing-established">Established: {{d.acf.established}}</div>
<div id="listing-about">About: {{d.acf.about}}</div>
<div id="listing-mailingaddress">Mailing Address: {{d.acf.mailing_address_}}, {{d.acf.mailing_address_2}}, {{d.acf.mailing_address_3}}, {{d.acf.mailing_town}}, {{d.acf.mailing_county}}, {{d.acf.mailing_postcode}}</div>
<div id="listing-directions">Directions: {{d.acf.directions}}</div>
<div id="scd-link">View on The Shooting Club Directory</div>
</div>
</div>
</div>
</body>
</div>
Here is a working code pen - http://codepen.io/anon/pen/yePYdq
Angular is a great JavaScript front-end framework to choose, and you're off to a good start, but a lot of changes could be made. I've made some suggested changes for easier ways to do things below.
See this CodePen for all changes.
It looks like you've grasped the idea of ng-repeat, but there's definitely a lot of repeated HTML and JS in your view and controller, so let's see if we can do better.
Let's try this without jQuery to avoid direct manipulation of the DOM. And instead of many controllers, we can do this with a single controller.
<div ng-app="MyApp">
<div ng-controller="MyController">
...
</div>
</div>
<script type="text/javascript">
var app = angular.module('MyApp', []);
app.controller('MyController', ...);
</script>
For the dropdown, we'll use ng-repeat in our view and display the names of the shooting types from our model
...
<select ng-model="selectedListing">
<option
ng-repeat="listingShootingType in listingShootingTypes"
value="{{listingShootingType.name}}">
{{listingShootingType.name}}
</option>
</select>
...
<script type="text/javascript">
...
// Our selections/filters
$scope.listingShootingTypes = [
'All',
'Air Rifle/Air Pistol',
'Clay',
'ABT',
'Double Trap',
'English Skeet',
'English Sporting',
'Fitasc',
'Olympic Skeet',
'Olympic Trap',
'Simulated Game',
'Sport Trap/Compact',
'Universal Trench',
'ZZ/Helice',
'Rifle',
'Centrefire Target Rifle',
'Gallery Rifle',
'Muzzle Loading',
'Practice Shotgun',
'Smallbore Rifle'
];
...
</script>
With only one controller, we can still use ng-repeat for each listing.
<div ng-repeat="d in data">
<h2 class="entry-title title-post">{{d.title}}</h2>
<div id="listing-image"><img src="{{d.acf.logo}}"></div>
<div id="listing-contact">Contact: {{d.acf.contact}}, {{d.acf.position}}</div>
<div id="listing-address-1">
{{d.acf.address_1}}, {{d.acf.address_2}} {{d.acf.address_3}} {{d.acf.town}} {{d.acf.county}} {{d.acf.postcode}}
</div>
<div id="listing-phone">Telephone: {{d.acf.telephone}}</div>
<div id="listing-mobile">Mobile: {{d.acf.mobile}}</div>
<div id="listing-email">Email: {{d.acf.email}}</div>
<div id="listing-website">Website: {{d.acf.website}}</div>
<div id="listing-established">Established: {{d.acf.established}}</div>
<div id="listing-about">About: {{d.acf.about}}</div>
<div id="listing-mailingaddress">Mailing Address: {{d.acf.mailing_address_}}, {{d.acf.mailing_address_2}}, {{d.acf.mailing_address_3}}, {{d.acf.mailing_town}}, {{d.acf.mailing_county}}, {{d.acf.mailing_postcode}}</div>
<div id="listing-directions">Directions: {{d.acf.directions}}</div>
<div id="scd-link">View on The Shooting Club Directory</div>
</div>
Finally... How do we only display listings that match our selected shooting type from the dropdown? We could use a custom Angular filter!
...
<div ng-repeat="d in data | filter:isSelectedListing">
...
<script type="text/javascript">
...
// Let's define a custom Angular filter because the WordPress JSON is complex
$scope.isSelectedListing = function(listing) {
// Show nothing if nothing is selected
if (angular.isUndefined($scope.selectedListing) || $scope.selectedListing == '') {
return false;
}
// Show all if 'All' is selected
if ($scope.selectedListing == 'All') {
return true;
}
// If the shooting type we're looking for is present, show the listing.
// To do this, we parse the WordPress JSON object model.
if (angular.isDefined(listing.terms.listing_shooting_type)) {
for (var i = 0; i < listing.terms.listing_shooting_type.length; i++) {
if (listing.terms.listing_shooting_type[i].name == $scope.selectedListing) {
return true;
}
}
}
return false;
};
...
</script>
Hopefully this gives you an idea of how we better leverage ng-repeat + DRY :)
The entire CodePen is here.
Today is my first day with Angular.js , and I stuck at a basic controller :
my APP.js
(function()
{ var app = angular.module('store', [ ] );
app.controller('StoreController', function()
{
this.product = gem;
});
var gem = [
{name:'John', price:25, description:'boy',soldout: false,canpurchase:true},
{name:'Kohn', price:25, description:'boy',soldout: false,canpurchase:true}
]
//not mentioned:false
})();
Index.HTML
<!DOCTYPE html>
<html ng-app="store">
<script src="js/angular.min.js" type="text/javascript"></script>
<link href="css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
<title>Purple</title>
</head>
<body ng-controller = "StoreController as store">
<script src="js/app.js" type="text/javascript"></script>
<h1>{{"Create your CV"}}</h1>
<div ng-repeat="products in store.product">
<div ng-hide="store.product.soldout">
<h1> {{store.product.name}} </h1>
<h2><em class="pull-right">{{store.product.price | currency}}</em></h2>
<h3> {{store.product.description}} </h3>
<button ng-show = "store.product.canpurchase"> Add to cart </button>
</div>
</div></body></html>
My code is working fine , but NG - repeat is not working, if I don't choose ng-repeat and display each item as an array then I am getting a display but not with "ng-repeat" .. Any idea's what am I missing ?
Please dont mark this as negative, I have done a lot of research before asking this question
Code on fiddle : http://jsfiddle.net/68Dkz/2/
Here is working version using controller alias store as shown. Note that product was changed to products in controller since the array contains more than one product. I think you are gtting confused about which is array and which is the individual item within the ng-repeat due to this
<div ng-repeat="product in store.products">
<div ng-hide="product.soldout">
<h1> {{product.name}} </h1>
<h2><em class="pull-right">{{store.product.price | currency}}</em></h2>
<h3> {{product.description}} </h3>
<button ng-show="product.canpurchase">Add to cart</button>
</div>
</div>
DEMO
store is your module not your scope you don't need it in the iteration, do products in product instead
<div ng-repeat="products in product">
<div ng-hide="products.soldout">
<h1> {{products.name}} </h1>
<h2><em class="pull-right">{{products.price | currency}}</em></h2>
<h3> {{products.description}} </h3>
<button ng-show = "products.canpurchase"> Add to cart </button>
</div>
</div>
stop aliasing your controller, it is unnecessary and may cause issues with the html compiler
using products as your iterator is confusing, I would suggest making the collection products and the iterator product
I know there are other questions about this but they don't seem to solve my problem.
This what my output is, and I thought it should be an accordion
I am fairly new to Angular so I may be missing something simple, but I can't seem to see it. This is going to go into a larger app that I am making, but I wanted to get it to work outside of that first.
Any help is appreciated.
Code:
demo.html
<!DOCTYPE html>
<html ng-app='myApp' >
<head>
<script src="js/app.js"></script>
<script scr="js/ui-bootstrap-tpls-0.10.0"></script>
<script src="js/angular.js"></script>
<link href="css/bootstrap.css" rel="stylesheet">
<title>Accordion Test</title>
</head>
<body>
<div class="col-md-3">
<div ng-controller="AccordionDemo">
<label class="checkbox">
<input type="checkbox" ng-model="oneAtATime">
Only open one at a time
</label>
<accordion close-others="oneAtATime">
<accordion-group heading="Item1" is-open="true">
the contenct of item one
</accordion-group>
<accordion-group heading = {{group.title}} ng-repeat="group in groups">
{{group.content}}
</accordion-group>
<accordion-group heading="{{dynamicitem}}">
<p>The body of the accordion group lol</p>
<button class="btn btn-default btn-lg glyphicon glyphicon-plus-sign" ng-click="addItem()">Add new items</button>
<div ng-repeat="item in items">{{item}}</div>
</accordion-group>
<accordion-group is-open="isopen">
<accordion-heading>
Open and Close <i class="pull-right glyphicon" ng-class=" {'glyphicon-chevron-down':isopen, 'glyphicon-chevron-right': !isopen} "></i>
</accordion-heading>
Your content is here
</accordion-group>
</accordion>
</div>
</div>
app.js
angular.module('myApp', ['ui.bootstrap']);
function AccordionDemo($scope){
$scope.oneAtATime = true;
$scope.groups = [
{
title: "Dynamic member 1",
content: "member 1 body"
},
{
title :"Dynamic member 2",
content :"member 2 body"
}
];
$scope.dynamicitem = 'Dynamic Item';
$scope.items = ['item 1', 'item 2', 'item 3'];
$scope.addItem = function(){
var newItem = $scope.items.length + 1;
$scope.items.push('Item' + newItem);
};
}
Edit:
Is it anything to do with the
<accordion-group is-open="isopen">
block? As the isopen might not bind to anything?
Plunk http://plnkr.co/edit/npZ35bGLiPkmVqaw5l4J?p=preview
as Ashesh said you had the angular paths wrong, you also have a working example on Angular Ui Team for the accordion control.
live example:
http://plnkr.co/edit/6zhm49PCgPZr8wKD5Szr?p=preview
You had the angular paths wrong, this, for example, gets the job done. You can start from there.