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.
Related
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>
I have an accordion object in AngularJS that is data driven. Here is what my html looks like:
HTML:
<div class="field-accordion" ng- if="field.fieldAccordion">
<ul class=a ccordion>
<li ng-repeat="fieldAccordion in field.fieldAccordion" ng- click="accordion.current = fieldAccordion.fieldName">
{{ fieldAccordion.fieldName }}
<ul ng-show="accordion.current == fieldAccordion.fieldName">
<li ng-repeat="fieldSub in fieldAccordion.fieldSub">
{{fieldSub.fieldName}}
</li>
</ul>
</li>
</ul>
</div>
Then in my JS file, I simply use it like this:
JS:
app.controller("myCtrl", function($scope) {
$scope.mySettings({
Header: '',
Title: '',
Img: '',
fieldAccordion: [{
// "this is my accordion list"
This works great for me. Whenever I click on the parent, it expands. The problem that I'm having is I can't get it to collapse. I am also trying to do it while keeping everything data driven like it is now. Is there anything I can change in my HTML to allow the text to collapse after expanding ?
Thank you
So the problem is because of a new scope being created, what you need to know is ng-if and ng-r creates a new scope, I checked your code and the ng-repeat is the root cause of the issue! hence the variable is not updating and the accordion is not toggling. Here is a simple way to update the parent controller using the $parent.
I have created a mockup highlighting the issue. So instead of updating accordion.current which will update the scope created by the ng-if you can just give it as $parent.accordion.current in the ng-click which will update the parent scope and the variable will be available for the ng-show and the accordion toggling works as expected.
Below is a working snippet, let me know if this fix solved your issue!
var app = angular.module('myApp', []);
app.controller('MyController', function MyController($scope) {
$scope.field = {
Header: '',
Title: '',
Img: '',
fieldAccordion: [{
fieldName: "one",
fieldSub: [{
fieldName: "oneone"
}]
}, {
fieldName: "two",
fieldSub: [{
fieldName: "twotwo"
}]
}]
};
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller='MyController' ng-app="myApp">
<div class="field-accordion" ng-if="field.fieldAccordion">
<ul class="accordion">
<li ng-repeat="fieldAccordion in field.fieldAccordion" ng-click="$parent.accordion.current = fieldAccordion.fieldName">
{{ fieldAccordion.fieldName }}
<ul ng-show="accordion.current == fieldAccordion.fieldName">
<li ng-repeat="fieldSub in fieldAccordion.fieldSub">
{{fieldSub.fieldName}}
</li>
</ul>
</li>
</ul>
</div>
</div>
I am working with AngularJs, Bootstrap 3. I want to toggle my glyphicon icon on my page. But i am able to do it. I followed the response at the stackoverflow question here.
I don't understand why i cannot display glyphicon with the toggle expression.
Here is my code :
<script>
angular.module("myapp", [])
.controller("MyController", function($scope) {
$scope.toggleIcon = false;
$scope.sort = function (sortBy) {
$scope.toggleIcon = !$scope.toggleIcon;
// sorting logic
};
} );
</script>
</head>
<body ng-app="myapp">
<div ng-controller="MyController" >
<div class="row">
Here the name to sort
Name <span class="glyphicon" ng-class="{glyphicon-sort-by-alphabet': toggleIcon, 'glyphicon-sort-by-alphabet-alt': !toggleIcon}"></span>
</div>
<div class="row">
Here the icon
<span class="glyphicon glyphicon-sort-by-alphabet"></span>
</div>
</div>
</body>
</html>
You can see the code on Plunker
Thank you.
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
We are making use of the angularjs accordion, however, our accordion is fairly big, and contains a lot of data.
What we are looking at doing is loading the data when the accordion opens. ie dont render the internal content, until a user click on the accordion header.
Below is how we are using the accordion at the moment:-
<accordion close-others="false">
<accordion-group heading="{{result.ReceivedDateTime}}{{result.OrderName}}" ng-repeat="result in resultsbyorder">
<table id="tbl" class="table table-striped table-bordered" ng-repeat="Grid in result.Results">
<tr ng-repeat="item in Grid" ng-show="$first">
<th ng-repeat="somat in item">
{{somat.ColumnHeader}}
</th>
</tr>
<tr ng-repeat="item in Grid">
<td ng-repeat="somat in item">
{{somat.ColumnValue}}
</td>
</tr>
</table>
</accordion-group>
</accordion>
as a side note, is it possible to only render the accordion headers that are displayed on the screen, then render the remaining on scrolling?
I think what you are better off doing is to compile it once when it is opened the first time.
That way, you don't have to compile the same content again, even though it was compiled before the last time the accordion group was opened.
Over the top of my head, I can think of using the ng-switch directive. As you must be aware, this directive allows to display DOM elements conditionally, based on the case variable.
However, where this directive differs from the ng-show or ng-hide directive is that the contents within the case statement are not compiled until the corresponding case variable is matched.
Thus, what you could do is have the following setup in your HTML document:
<accordion close-others="oneAtATime">
<accordion-group is-open="isopen">
<accordion-heading>
Accordion Heading
</accordion-heading>
<div ng-switch on="isopen">
<div ng-switch-when="true">
<!-- Content that should be compiled when the accordion is opened
goes here -->
</div>
</div>
</accordion-group>
</accordion>
A demonstration of the same can be found in this plunkr.
Also, I believe ng-if directive also achieves the same effect. So, you can use either of the directives to achieve your requirements.
I am doing this very thing at the moment and have found that Angular likes using a collection (even if it's just a single element) to make the accordion, to wit if you do, you can bind the is-open to an element on that group and then setup a watch on that group in the controller. Consider the following (think of putting an ajax call to get your data instead of logging to console):
var ngtestapp = angular.module("ngtestapp", ['ui.bootstrap']);
ngtestapp.controller("ngTestController", function ($scope) {
$scope.userComments = [
{
RowId: 123,
DateCreated: new Date(2015, 1, 2, 0, 0, 0, 0),
CreatedBy: 564,
Message: 'Carpe Dieum',
CreatedByDisplayName: 'Daniel Graham'
},
{
RowId: 124,
DateCreated: new Date(2015, 1, 5, 0, 0, 0, 0),
CreatedBy: 562,
Message: 'That was awesome',
CreatedByDisplayName: 'Peter Griffin'
}
];
$scope.feedbackGroup = [{ title: "User Comments", open: false }];
$scope.$watch('feedbackGroup', function (feedbackGroup) {
if (feedbackGroup[0].open) {
console.log("opened feedback group.");
} else {
console.log("closed feedback group.");
}
}, true);
$scope.userTaskNote = "user task test note";
});
.nav, .pagination, .carousel, .panel-title a { cursor: pointer; }
<html lang="en" ng-app="ngtestapp">
<head>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.1/ui-bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.1/ui-bootstrap-tpls.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
</head>
<body>
<div ng-controller="ngTestController">
<div class="container-fluid">
<accordion close-others="true">
<accordion-group ng-repeat="group in feedbackGroup" heading="{{group.title}}" is-open="group.open">
<ul class="list-group">
<li class="list-group-item" ng-repeat="comment in userComments track by $index | orderBy:comment.DateCreated">
<span class="badge" ng-bind="comment.DateCreated | date:'shortDate'"></span>
<strong ng-bind="comment.CreatedByDisplayName">Username</strong> <p ng-bind="comment.Message">comment</p>
</li>
</ul>
</accordion-group>
<accordion-group is-open="false" heading="Other">
<textarea class="form-control input-sm" ng-model="userTaskNote" placeholder="Add a task note here..."></textarea>
</accordion-group>
</accordion>
</div>
</div>
</body>
</html>