3

I am pretty new to angular and i cant get it right.

inside the following example i am trying to show the answer to a question after the user clicks on the corresponding button. before the answer is shown i want to run a function that checks if the user has the privilege to reveal the answer. in the example i assume he has the rights.

what i have to do to to remove the "ng-hide" class in the row where the button was clicked.

i appreciate any kind of help. thanks 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>

2
  • 1
    I would use a bit more than just simple arrays of Strings... I would create a array of objects containing all the flags you need and programe a bit more object-oriented. Like this: plunker Commented Jul 9, 2015 at 13:49
  • hi, thanks for you answer. Yes you are completely right, i wanted to keep it simple for the question to focus on the angular part. In the end all the date will be in a mySQL database Commented Jul 9, 2015 at 17:11

4 Answers 4

4

Here's a complete working example.

Things I changed:

  • The answers are now stored as a property of each question. This makes the code neater (no need to track by $index).
  • The ng-show directive is used as an attribute instead of a class, and is bound to a showAnswers property of the question.
  • The showme function sets the showAnswers property to true when you click the button.

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>

Sign up to request clarification or add additional context in comments.

2 Comments

Glad somebody actually thought of using objects. :)
@Mike: thanks a lot for your answer! this really helled :-)
1

Try 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; 
    }
}]);

Fiddle

Comments

0

Taking your 'privilege' request in consideration, I think you will want to create a condition. Instead of adding the class ng-hide, use ng-hide, ng-show or ng-if like this:

<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 the td if both statements are true. If one or both of them are false, it won't show the element.

then in your controller:

$scope.hideme = function(index) {
    $scope.hasPrivilege = getPrivilege();
    $scope.show[index] = true;
}

the getPrivilege() function should return true or false based on whether the user has the privilege.

Comments

0

Okay 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 toggle

if you want to hide the Answer again on the same button This shows and hides the button depending if its 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

8 Comments

Yep but this won't work in the ng-repeat. All answers will be shown.
you can simply pass the Index of the Question <button ng-click="showAnswer($index)">This is the answer!!!</span> and then return $scope.answers[passedIndex]
Add it to your answer then ;-)
added it to my answer
As soon as the question array gets sorted or filtered, your solution breaks. It would have been much better to introduce a question object containing: the question, answer and a display property. Even adding a question requires you to change the code in two places.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.