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>