coderain blog

AngularJS ng-class Toggle: How to Fix Lexer Error When Using Ternary Operator for Class Switching

AngularJS, despite being superseded by Angular, remains a cornerstone of many legacy web applications. One of its most powerful directives for dynamic styling is ng-class, which allows you to conditionally apply CSS classes to elements. A common pattern for class switching is using the ternary operator (condition ? 'class-if-true' : 'class-if-false'), as it offers a concise way to toggle classes based on a boolean or expression.

However, developers often encounter a "lexer error" when using the ternary operator with ng-class. This error occurs due to miscommunication between AngularJS’s expression parser (lexer) and the syntax of the ternary operator, especially when class names contain special characters (e.g., hyphens) or are not properly formatted.

In this blog, we’ll demystify the lexer error, explain why it happens, and provide a step-by-step guide to fixing it. By the end, you’ll confidently use the ternary operator with ng-class to toggle classes without syntax issues.

2025-12

Table of Contents#

  1. Understanding the ng-class Directive
  2. The Ternary Operator Approach to Class Switching
  3. What is a Lexer Error?
  4. What Causes the Lexer Error with Ternary Operators?
  5. Step-by-Step Fix: Resolving the Lexer Error
  6. Practical Examples: Incorrect vs. Correct Syntax
  7. Best Practices for Using Ternary with ng-class
  8. Conclusion
  9. References

Understanding the ng-class Directive#

Before diving into the error, let’s recap how ng-class works. The ng-class directive dynamically applies CSS classes to an element based on an expression. It supports three syntaxes:

1. Object Syntax#

Maps class names to boolean conditions. Classes are applied if their corresponding condition is true.

<div ng-class="{ 'active': isActive, 'disabled': isDisabled }"></div>  

2. Array Syntax#

Applies a list of classes (useful for static classes combined with dynamic ones).

<div ng-class="['static-class', dynamicClassVariable]"></div>  

3. Expression Syntax#

Evaluates an expression that returns a string, object, or array of classes. This is where the ternary operator fits in:

<div ng-class="condition ? 'class-if-true' : 'class-if-false'"></div>  

The ternary operator is popular here for its brevity when switching between two classes. However, this is also where the lexer error often strikes.

The Ternary Operator Approach to Class Switching#

The ternary operator (condition ? exprIfTrue : exprIfFalse) is a shorthand for an if-else statement. In ng-class, it returns a class name (or multiple classes) based on a condition. For example:

<!-- Toggle 'active' class based on isActive flag -->  
<div ng-class="isActive ? 'active' : 'inactive'"></div>  

This should apply active when isActive is true, and inactive when false. But if not formatted correctly, AngularJS’s parser may throw a lexer error.

What is a Lexer Error?#

AngularJS uses a lexer (part of the $parse service) to tokenize and parse expressions. The lexer breaks down the expression into meaningful tokens (e.g., variables, operators, strings) before the parser evaluates it. A "lexer error" occurs when the lexer encounters unexpected or invalid tokens, such as unquoted special characters or malformed syntax.

For example, if the lexer encounters a hyphen (-) in an unquoted string, it may misinterpret it as a subtraction operator, leading to a tokenization failure.

What Causes the Lexer Error with Ternary Operators?#

The most common cause of lexer errors when using the ternary operator with ng-class is unquoted class names containing special characters (e.g., hyphens, underscores in some cases) or invalid expression syntax.

Key Culprits:#

  1. Unquoted Class Names with Hyphens: Class names like header-active or btn-primary contain hyphens. If unquoted, the lexer interprets the hyphen as a subtraction operator (e.g., header - active), leading to a syntax error.

  2. Missing Quotes for String Literals: Class names are string literals, but developers often forget to wrap them in quotes. AngularJS then treats them as variables (e.g., active is assumed to be a scope variable, not a string).

  3. Malformed Ternary Expressions: Syntax errors like missing colons (:), unbalanced parentheses, or mixing object/array syntax with ternary can confuse the lexer.

Step-by-Step Fix: Resolving the Lexer Error#

To fix the lexer error when using the ternary operator with ng-class, follow these steps:

Step 1: Enclose Class Names in Quotes#

Class names are string literals—always wrap them in single quotes (') or double quotes ("). This tells the lexer to treat them as strings, not variables or operators.

Step 2: Validate Ternary Syntax#

Ensure the ternary operator follows the format: condition ? 'class-if-true' : 'class-if-false'. Check for:

  • A valid condition (e.g., isActive, user.role === 'admin').
  • A colon (:) separating the "if-true" and "if-false" branches.
  • No trailing commas or missing parentheses (for nested ternaries).

Step 3: Test the Expression#

If the error persists, test the expression in AngularJS’s $parse service to isolate issues. For example, in your controller:

// Test the ng-class expression  
var expression = "$parse('isActive ? 'active' : 'inactive')";  
var parsed = $parse(expression);  
console.log(parsed($scope)); // Should return 'active' or 'inactive'  

Practical Examples: Incorrect vs. Correct Syntax#

Let’s compare common incorrect patterns with their fixed versions to see the lexer error in action.

Example 1: Unquoted Hyphenated Classes (Error-Prone)#

Incorrect: Class names with hyphens are unquoted. The lexer interprets - as subtraction.

<!-- Lexer Error: "Unexpected token '-'" -->  
<div ng-class="isActive ? header-active : header-inactive"></div>  

Correct: Wrap hyphenated classes in quotes.

<!-- No error: Classes are treated as strings -->  
<div ng-class="isActive ? 'header-active' : 'header-inactive'"></div>  

Example 2: Multiple Classes in Ternary (Unquoted)#

Incorrect: Multiple classes without quotes are misread as variables.

<!-- Lexer Error: "Unexpected token 'bold'" -->  
<div ng-class="isValid ? success bold : error italic"></div>  

Correct: Wrap multiple classes in a single quoted string.

<!-- Applies "success bold" or "error italic" -->  
<div ng-class="isValid ? 'success bold' : 'error italic'"></div>  

Example 3: Nested Ternaries (Missing Parentheses)#

Incorrect: Nested ternaries without parentheses can confuse the lexer.

<!-- Lexer Error: "Expected ':' but saw '?'" -->  
<div ng-class="user.role === 'admin' ? 'admin' : user.role === 'editor' ? 'editor' : 'guest'"></div>  

Correct: Use parentheses to group nested ternaries.

<!-- Clear grouping prevents lexer confusion -->  
<div ng-class="user.role === 'admin' ? 'admin' : (user.role === 'editor' ? 'editor' : 'guest')"></div>  

Best Practices for Using Ternary with ng-class#

To avoid lexer errors and write maintainable code:

1. Always Quote Class Names#

Even for single-word classes (e.g., active), quoting prevents ambiguity. If active is a scope variable, Angular will throw a different error, but quoting ensures it’s treated as a string.

2. Avoid Overly Nested Ternaries#

Nested ternaries can become unreadable and error-prone. For 3+ conditions, use object syntax instead:

<!-- Better than nested ternaries -->  
<div ng-class="{  
  'admin': user.role === 'admin',  
  'editor': user.role === 'editor',  
  'guest': user.role === 'guest'  
}"></div>  

3. Keep Expressions Simple#

Move complex logic to the controller. For example:

// Controller  
$scope.getClass = function() {  
  return $scope.isActive ? 'active' : 'inactive';  
};  
<!-- Template (cleaner and easier to debug) -->  
<div ng-class="getClass()"></div>  

4. Test for Edge Cases#

If classes contain special characters (e.g., my-class-123), ensure quotes are applied. AngularJS’s lexer is strict about unquoted special characters.

Conclusion#

The lexer error when using the ternary operator with ng-class is almost always caused by unquoted class names or malformed expressions. By wrapping class names in quotes, validating ternary syntax, and following best practices like avoiding deep nesting, you can easily resolve this issue.

Remember: ng-class is powerful, but AngularJS’s expression parser demands precision. With the right syntax, the ternary operator remains a concise tool for dynamic class switching in legacy AngularJS applications.

References#