Angular way: show or hide element after button click
I am new to angular and I cannot seem to fix this.
In the following example, I'm trying to show the answer to a question after the user clicks on the corresponding button. before the response is shown, I want to run a function that checks if the user is allowed to expand the response. in the example I am assuming he has rights.
what i need to do is to remove the "ng-hide" class on the line where the button was clicked.
I appreciate any help. thank you in advance
var myApp = angular.module('myApp', []);
myApp.controller('QuestionCtlr', ['$scope', '$log', function($scope, $log) {
$scope.questions = [
["what is 1+1?"],
["what color of the sky"],
["what is the answer to the universe"]
];
$scope.answers = [
2, ["blue, black or orange"],
40
];
$scope.hideme = function(i) {
$log.log("element " + i + " was cicked");
//this will be detemined within a fct, so lets asume the has the according rights
var userPrivilege = true;
if (userPrivilege) {
//HOW TO: show the answer with the index i
}
}
}]);
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<!-- angular -->
<script src="https://code.angularjs.org/1.4.0/angular.min.js"></script>
<script src="app.js"></script>
<!-- jquery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<!-- bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</head>
<body ng-controller=QuestionCtlr>
<table class="table table-hover">
<thead>
<tr>
<th>Question</th>
<th>Answer</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="q in questions track by $index">
<td>{{q[0]}}</td>
<td class = "ng-hide">{{q[0]}}</td>
<td>
<button type="button" ng-click="hideme($index)" class="btn btn-default">show me</button>
</td>
</tr>
</tbody>
</table>
</body>
</html>
source to share
Here's a complete working example.
Things I changed:
- Now the answers are saved as a property of each question. This simplifies the code (not necessary
track by $index
). - The ng-show directive is used as an attribute instead of a class and is bound to the
showAnswers
question property . - The function
showme
sets the propertyshowAnswers
totrue
when the button is clicked.
var myApp = angular.module('myApp', []);
myApp.controller('QuestionCtlr', ['$scope', '$log', function($scope, $log) {
$scope.questions = [
{question: "what is 1+1?", answers: [2]},
{question: "what color of the sky", answers: ["blue", "black", "orange"]},
{question: "what is the answer to the universe", answers: [42]}
];
$scope.showme = function(q) {
$log.log("question " + q.question + " was cicked");
var userPrivilege = true;
if (userPrivilege) {
q.showAnswers = true;
}
}
}]);
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<!-- angular -->
<script src="https://code.angularjs.org/1.4.0/angular.min.js"></script>
<script src="app.js"></script>
<!-- jquery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<!-- bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</head>
<body ng-controller=QuestionCtlr>
<table class="table table-hover">
<thead>
<tr>
<th>Question</th>
<th colspan="2">Answer</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="q in questions">
<td >{{q.question}}</td>
<td ng-show="q.showAnswers">
<div ng-repeat="a in q.answers">{{a}}</div>
</td>
<td>
<button type="button" ng-click="showme(q)" class="btn btn-default">show me</button>
</td>
</tr>
</tbody>
</table>
</body>
</html>
source to share
Try it in html
<table class="table table-hover">
<thead>
<tr>
<th>Question</th>
<th>Answer</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="q in questions">
<td>{{q[0]}}</td>
<td ng-class="{hide : active != $index}">{{answers[$index]}}</td>
<td>
<button type="button" ng-click="hideme($index)" class="btn btn-default">show me</button>
</td>
</tr>
</tbody>
</table>
angular
var myApp = angular.module('myApp', []);
myApp.controller('QuestionCtlr', ['$scope', '$log', function($scope, $log) {
$scope.questions = [
["what is 1+1?"],
["what color of the sky"],
["what is the answer to the universe"]
];
$scope.answers = [
2, ["blue, black or orange"],
40
];
$scope.active = null;
$scope.hideme = function(i) {
$scope.active = i;
}
}]);
source to share
Ok first of all you can use
ng-if="condition" //gets only rendered if condition is true
ng-show="condition" //shows when condition is true
ng-hide="condition" //hides when condition is true
So on your button
ng-click="showAnswer()"
In your controller
$scope.displayAnswer = false;
$scope.showAnswer = function(){
if(hasRights == true){
$scope.displayAnswer = true //this is used for the hide and show
}
}
In your html 3 possible ways
<span ng-if="displayAnswer == true">This is the answer!!!</span>
<span ng-show="displayAnswer == true">This is the answer!!!</span>
<span ng-hide="displayAnswer == false">This is the answer!!!</span>
<button ng-click="showAnswer()">This is the answer!!!</span>
2nd solution with switchover
if you want to hide the response on the same button again This shows and hides the button depending on whether it is currently shown or hidden
$scope.toggleAnswer = function(displayAnswer){
if(hasRights == true && $scope.displayAnswer == false){
$scope.displayAnswer = true //this is used for the hide and show
}else if($scope.displayAnswer == true){
$scope.displayAnswer = false;
}
}
2nd Html
<span ng-if="displayAnswer == true">This is the answer!!!</span>
<button ng-click="toggleAnswer(displayAnswer)">This is the answer!!!</span>
In your case
<button ng-click="toggleAnswer($index)">Hide / Show</button>
And in your controller
$scope.answers = [{A: 2, show: false},{A: 'blue', show: false}]
$scope.toggleAnswer = function(index){
if(hasRights == true){
$scope.answers[index].show = true //this is used for the hide and show
}
}
in HTML
<span ng-if="item.show == true">The Answer !!</span>
//the item is coming from item in Answers from the ng-repeat
source to share
Given your request for "privilege", I think you need to create a condition. Instead of adding the ng-hide class, use ng-hide, ng-show, or ng if so:
<td ng-show="hasPrivilege && show[$index]">
<!--or ng-hide or ng-if-->
and your button:
<button type="button" ng-click="hideme($index)">
This will show td if both statements are true. If one or both of them are false, the item will not be displayed.
then in your controller:
$scope.hideme = function(index) {
$scope.hasPrivilege = getPrivilege();
$scope.show[index] = true;
}
the function getPrivilege()
should return true or false based on whether the user has a privilege.
source to share