1

Hopefully someone can point my in the right direction.

I am building a web app and part of it requires a user to click a button as fast as they can to obtain a score. The design dictates that I will need to show this score in double digits i.e 9 would be 09 so for styling I need to wrap span tags around each digit.

I have got everything working as required, I'm just having an issue with outputting the score that is wrapped in span tags as rendered html in my view.

I've put together a fiddle for the section that is causing me problems. Any advice, help, best practices etc is much appreciated.

What I've tried:

I've included a few of the things I've tried. Basically they involve using $sce and trying to ng-bind-html in the view. Attempt 3 seems the most logical to me but the $scope.count isn't being updated. I'm guessing I need to add a $watch or $apply function to keep it binded? but I'm not too sure how to implement it or even if this is good practice. Also, because I'm outputting html is it better practice to do this in a directive?

Fiddle http://jsfiddle.net/funkycamel/gvxpnvqp/4/

HTML

<section ng-app="myApp">
<div ng-controller="MyController">

    <button ng-click="add(1)">add</button>

    <!-- First attempt -->
    <p class="first-attempt">{{ pad(count) }}</p>

    <!-- Second attempt -->
    <!-- in order for this attempt to work I have to call the pad2 function which
    returns trustedHtml -->
    {{ pad2(count) }}
    <p class="second-attempt" ng-bind-html="trustedHtml"></p>

    <!-- Third attempt -->
    <p class="third-attempt" ng-bind-html="moreTrustedHtml"></p>

</div>

Javascript

var app = angular.module('myApp', []);
app.controller('MyController', ['$scope', '$sce', function ($scope, $sce) {

// Set initial count to 0
$scope.count = 0;

// function to add to $scope.count
$scope.add = function (amount) {
    $scope.count += amount;
};

// Attempt 1
// make sure number displays as a double digit if
// under 10. convert to string to add span tags
$scope.pad = function (number) {
    var input = (number < 10 ? '0' : '') + number;
    var n = input.toString();
    var j = n.split('');
    var newText = '';
    var trustedHtml = '';

    for (var i = 0; i < n.length; i++) {
        newText += '<span>' + n[i] + '</span>';
    }

    return newText;
};


// Attempt 2 - trying to sanitise output
// same as above just returning trusted html
$scope.pad2 = function (number) {
    var input = (number < 10 ? '0' : '') + number;
    var n = input.toString();
    var j = n.split('');
    var newText = '';
    var trustedHtml = '';

    for (var i = 0; i < n.length; i++) {
        newText += '<span>' + n[i] + '</span>';
    }

    // return sanitised text, hopefully
    $scope.trustedHtml = $sce.trustAsHtml(newText);
    return $scope.trustedHtml;
};

// Attempt 3
// Trying to sanitise the count variable
$scope.moreTrustedHtml = $sce.trustAsHtml($scope.pad($scope.count));

}]);

These currently output

<span>0</span><span>0</span>

<span>0</span><span>0</span>

00
00

Again any advice/help is greatly appreciated.

12
  • This is going against the grain of angular. Commented Mar 5, 2015 at 14:07
  • Just use ng-show and bind the count to a $scope var Commented Mar 5, 2015 at 14:08
  • @CallumLinington: Care to elaborate? Commented Mar 5, 2015 at 14:14
  • @tymeJV: ng-show shows or hides an html element? The count is a scope variable and is holding the count. The issue I have is outputting the spans with that count Commented Mar 5, 2015 at 14:16
  • You've got controllers creating HTML code .... this isn't the angular way. Directives do stuff with DOM. Controllers just tie together services and view interactions. Commented Mar 5, 2015 at 14:20

1 Answer 1

1

Far simpler solution:

HTML

<p>{{ count < 10 ? '0' + count : count}}</p>

Controller:

app.controller('MyController', ['$scope', function ($scope) {
    $scope.count = 0;

    $scope.add = function (amount) {
        $scope.count += amount;
    };
}]);

DEMO

If you prefer you can do the padding in the controller instead, just use another variable

app.controller('MyController', ['$scope', function ($scope) {
    var count = 0;
    $scope.countText = '0';

    $scope.add = function (amount) {
        count += amount;
        $scope.countText = count < 10 ? '0' + count : count;
    };
}]);
Sign up to request clarification or add additional context in comments.

1 Comment

I like the idea of doing the pad directly in the html it's just I need the spans for styling, unless you could suggest a better way?

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.