How can I use AngularJS directive to apply css style for a string?


Tags: javascript,css,angularjs,angularjs-directive

Problem :

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>



Solution :

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>


    CSS Howto..

    How to avoid orphaned headings in CSS columns?

    How to figure out what is going on with this nice CSS horizontal menu? [closed]

    How to cancel HTML “onfocus” behavior?

    How to do letter spacing every two letters with CSS only?

    jquery/css: I want to change the bgcolor of row only after hovering for 1 or 2 seconds. How to achieve this?

    How can I make LIs push their siblings to the same height?

    How can I have columns like this in CSS? (image)

    how do I use standard GWT CSS style themes from non-GWT pages?

    How to display separate paragraphs in the same area using CSS HTML

    how to go bottom of a website like back to top using javascript?

    How do I simultaneously open child and sub-child of a parent, in jQuery accordion menu, when parent is clicked?

    How to make child divs visible in tympanus.net's CSS Radio Checked Tab Method

    How do I change the Default Design? [closed]

    How to overide CSS style of a class using jquery? [closed]

    How do I override a css value?

    How to remove the border line around the element in html and css?

    How to set min-font-size in CSS

    How can I force a table cell onto a new row

    how to access the styles from CSS

    how to make button in ionic + css

    How to use CSS transition to animate dropdown menu?

    How should I convert this PSD to HTML & CSS Menu

    How to make label inside div to be in the same position as lower ones

    How can I keep things aligned in an adaptive layout

    Hiding and Showing Content using CSS3, Want hidden state the be the default

    loading images to show them offline

    FontAwesome icon showing as black box. What CSS is needed to display icon?

    How can I change the paragraph formatting in the SharePoint RichHtmlField

    How to make ScrollPanel only visible when its inside widget is higher than it & not visible when its inside widget is shorter than it?

    Css How to add round corners when hover li element?