0

I have struggle with this problem for days, not knowing how to solve it.

The scenario is:

There is a string from database as QUESTION, and another string as ANSWER.

$scope.exam = {};
$timeout(function () {
    $scope.exam.QUESTION = 'Find the perimeter of a rhombus whose diagonals measure 12 and 16. <br />A.10<br />B.20  <br />C.40 <br />D.80 <br />';
    $scope.exam.ANSWER = 'D';
}, 500);

I use regular expression to split the choices of that QUESTION and apply css style button to the choices.

var myArray = /(^.*?)(?:<br ?\/?>)(A\s*?\.[\s\S]*?)(?:<br ?\/?>)(B\s*?\.[\s\S]*?)(?:<br ?\/?>)(C\s*?\.[\s\S]*?)(?:<br ?\/?>)(D\s*?\.[\s\S]*?)(?:<br ?\/?>)?<.*$/mg.exec(question);

If that choice is a correct answer, then apply hvr-bounce-in hvr-sweep-to-right. Otherwise, apply hvr-buzz-out style.

ans = "<br /><a ng-class=\"(scope.choiceanswer === v.substring(0, 1)) ? \'hvr-bounce-in hvr-sweep-to-right\':\'hvr-buzz-out\'\">" +v +"</a>";

But all my choices are applied by the same style hvr-bounce-in hvr-sweep-to-right.

How can I solve it?

'use strict';

angular.module('myApp', [])

    .controller('View2Ctrl', function ($scope, $timeout) {
        $scope.exam = {};
        $timeout(function () {
            $scope.exam.QUESTION = 'Find the perimeter of a rhombus whose diagonals measure 12 and 16. <br />A.10<br />B.20  <br />C.40 <br />D.80 <br />';
            $scope.exam.ANSWER = 'D';
        }, 500);


    })
    .directive('choicebutton', function ($compile, $interpolate, $timeout) {
        return {
            restrict: 'A',
            scope: {
                choiceanswer: '&',
                question: '&',
                choiceClass: '&'
            },
            replace: true,
            link: function (scope, ele, attrs) {
                scope.$watch(scope.question, function (question) {
                    if (question) {
                        var result = "";

                        var ans ='';
                        console.log(question);
                        console.log(scope.choiceanswer());
                        var myArray = /(^.*?)(?:<br ?\/?>)(A\s*?\.[\s\S]*?)(?:<br ?\/?>)(B\s*?\.[\s\S]*?)(?:<br ?\/?>)(C\s*?\.[\s\S]*?)(?:<br ?\/?>)(D\s*?\.[\s\S]*?)(?:<br ?\/?>)?<.*$/mg.exec(question);
                        console.log(myArray.length);
                        angular.forEach(myArray, function (v, l) {
                            console.log(v, l);
                            if (l > 0) {
                                console.log(v.substring(0,1));
                                console.log(scope.choiceanswer() == v.substring(0,1));
                                ans = "<br /><a ng-class=\"(scope.choiceanswer === v.substring(0, 1)) ? \'hvr-bounce-in hvr-sweep-to-right\':\'hvr-buzz-out\'\">" +v +"</a>";
                                
                                console.log(ans);
                                result += ans;

                            }
                        });
                        console.log(result);
                        $timeout(function () {
                            ele.html(result);

                            $compile(ele.contents())(scope);
                        }, 0);
                    }
                });
            }
        };
    });
<link href="http://ianlunn.github.io/Hover/css/hover.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" ng-controller='View2Ctrl'>
 

<div choicebutton="exam.QUESTION"  class="text-info selectable" choiceanswer="exam.ANSWER" question="exam.QUESTION"  choiceClass="choiceClass"></div>
  
  </body>

2 Answers 2

1

Possibly in snippet i too many simplified your code, but your variant seems very complicated.

first, if question always have this format, you not need in regex and simple split work.

second, you generate string and compile it instead just use built-in template for directive.

third, in template string you use wrong scope and v, because you add it as text, so angular try get it from scope and always get undefined

'use strict';

angular.module('myApp', [])

.controller('View2Ctrl', function($scope, $timeout) {
    $scope.exam = {};
    $timeout(function() {
      $scope.exam.QUESTION = 'Find the perimeter of a rhombus whose diagonals measure 12 and 16. <br />A.10<br />B.20  <br />C.40 <br />D.80 <br />';
      $scope.exam.ANSWER = 'D';
    }, 500);

  })
  .directive('choicebutton', function($compile, $interpolate, $timeout) {
    return {
      template: '<div><span>{{qText}}</span>' +
        '<div ng-repeat="answer in answers">' +
        '    <a ng-class="{\'hvr-bounce-in hvr-sweep-to-right\':answer.selected, \'hvr-buzz-out\':!answer.selected}">{{answer.text}}</a>' +
        '</div></div>',

      restrict: 'A',
      scope: {
        choiceanswer: '=',
        question: '&',
        choiceClass: '&'
      },
      replace: true,
      link: function(scope, ele, attrs) {
        scope.$watch(scope.question, function(newQuestion, oldQuestion) {
          if (newQuestion === undefined || newQuestion === oldQuestion) return;
          var q = newQuestion.split('<br />');
          scope.qText = q.shift();
          scope.answers = q.map(function(item) {
            return {
              selected: item[0] === scope.choiceanswer,
              text: item
            };
          });
        });
      }
    };
  });
<link href="http://ianlunn.github.io/Hover/css/hover.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp" ng-controller='View2Ctrl'>


  <div choicebutton="exam.QUESTION" class="text-info selectable" choiceanswer="exam.ANSWER" question="exam.QUESTION" choiceClass="choiceClass"></div>

</div>

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

Comments

1
+50

'use strict';

angular.module('myApp', [])

    .controller('View2Ctrl', function ($scope, $timeout) {
        $scope.exam = {};
        $timeout(function () {
            $scope.exam.QUESTION = 'Find the perimeter of a rhombus whose diagonals measure 12 and 16. <br />A.10<br />B.20  <br />C.40 <br />D.80 <br />';
            $scope.exam.ANSWER = 'D';
        }, 500);


    })
    .directive('choicebutton', function ($compile, $interpolate, $timeout) {
        return {
            restrict: 'A',
            scope: {
                choiceanswer: '&',
                question: '&',
                choiceClass: '&'
            },
            replace: true,
            link: function (scope, ele, attrs) {
                scope.$watch(scope.question, function (question) {
                    if (question) {
                        var result = "";

                        var ans ='';
                        console.log(question);
                        console.log(scope.choiceanswer());
                        var myArray = /(^.*?)(?:<br ?\/?>)(A\s*?\.[\s\S]*?)(?:<br ?\/?>)(B\s*?\.[\s\S]*?)(?:<br ?\/?>)(C\s*?\.[\s\S]*?)(?:<br ?\/?>)(D\s*?\.[\s\S]*?)(?:<br ?\/?>)?<.*$/mg.exec(question);
                        console.log(myArray.length);
                        angular.forEach(myArray, function (v, l) {
                            console.log(v, l);
                            if (l > 0) {
                                console.log(v.substring(0,1));
                                console.log(scope.choiceanswer() == v.substring(0,1));
                                ans = "<br /><a class=\"" + (scope.choiceanswer() === v.substring(0, 1) ? 'hvr-bounce-in hvr-sweep-to-right' : 'hvr-buzz-out') + "\">" +v +"</a>";
                                
                                console.log(ans);
                                result += ans;

                            }
                        });
                        console.log(result);
                        $timeout(function () {
                            ele.html(result);

                            $compile(ele.contents())(scope);
                        }, 0);
                    }
                });
            }
        };
    });
<link href="http://ianlunn.github.io/Hover/css/hover.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" ng-controller='View2Ctrl'>
 

<div choicebutton="exam.QUESTION"  class="text-info selectable" choiceanswer="exam.ANSWER" question="exam.QUESTION"  choiceClass="choiceClass"></div>
  
  </body>

Your issue is the formatting of your ng-class attribute.

I believe you were trying to use ternary syntax however ng-class does not support such syntax. You provide it with an object hash or map {'some class to apply': scopeProperty} where scopeProperty is a value that will be evaluated and if truthy will cause the class to be applied.

To use the syntax you are you would <a class="{{angular expression}}">. This would also provide you a class that is data bound

Some example in fiddle: http://jsfiddle.net/7u9z2247/

However all of this is defunct in your implementation as your manually compiling it instead of using the template and not implementing any data binding from what i can see. So you can conditionally build your anchor string and apply the class that way, a very JQuery way of doing it.

ans = "<br /><a class=\"" + (scope.choiceanswer() === v.substring(0, 1) ? 'hvr-bounce-in hvr-sweep-to-right' : 'hvr-buzz-out') + "\">" +v +"</a>"

Comments

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.