or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

angular-wrappers.mdbest-practices.mddeprecated-features.mddevelopment-conventions.mderror-prevention.mdindex.mdnaming-conventions.md
tile.json

best-practices.mddocs/

Best Practices Rules

Rules designed to prevent mistakes and prescribe better ways of doing things in AngularJS applications. They help avoid footguns and enforce established Angular patterns.

Capabilities

Component Limit

Limits the number of Angular components per file to maintain code organization.

/**
 * Limit the number of angular components per file
 * Enforces separation of concerns and maintainable file sizes
 * Linked to John Papa's Angular Style Guide y001
 */
const componentLimit = {
  meta: {
    docs: { url: "https://github.com/Gillespie59/eslint-plugin-angular/blob/master/docs/rules/component-limit.md" };
    schema: [{ type: "number" }];
  };
  create: (context: ESLintContext) => ESLintVisitor;
};

Controller As Route

Requires the use of controllerAs syntax in routes or states.

/**
 * Require the use of controllerAs in routes or states
 * Promotes the controller-as pattern for better scoping
 * Linked to John Papa's Angular Style Guide y031
 */
const controllerAsRoute = {
  meta: {
    docs: { url: "https://github.com/Gillespie59/eslint-plugin-angular/blob/master/docs/rules/controller-as-route.md" };
    schema: [];
  };
  create: (context: ESLintContext) => ESLintVisitor;
};

Usage Example:

// ✗ BAD - Missing controllerAs in route
$routeProvider.when('/users', {
  templateUrl: 'users.html',
  controller: 'UsersController'
});

// ✓ GOOD - Using controllerAs syntax
$routeProvider.when('/users', {
  templateUrl: 'users.html',
  controller: 'UsersController',
  controllerAs: 'vm'
});

Controller As VM

Requires and specifies a capture variable for this in controllers.

/**
 * Require and specify a capture variable for this in controllers
 * Enforces consistent variable naming for controller context
 * Linked to John Papa's Angular Style Guide y032
 */
const controllerAsVm = {
  meta: {
    docs: { url: "https://github.com/Gillespie59/eslint-plugin-angular/blob/master/docs/rules/controller-as-vm.md" };
    schema: [{ type: "string" }];
  };
  create: (context: ESLintContext) => ESLintVisitor;
};

Usage Example:

// ✗ BAD - No capture variable for this
function UsersController() {
  this.users = [];
  this.addUser = function() {
    // 'this' context can be confusing
  };
}

// ✓ GOOD - Using capture variable
function UsersController() {
  var vm = this;
  vm.users = [];
  vm.addUser = function() {
    // Clear reference to controller context
  };
}

Controller As

Disallows assignments to $scope in controllers when using controllerAs pattern.

/**
 * Disallow assignments to $scope in controllers
 * Enforces controller-as pattern instead of scope binding
 * Linked to John Papa's Angular Style Guide y031
 */
const controllerAs = {
  meta: {
    docs: { url: "https://github.com/Gillespie59/eslint-plugin-angular/blob/master/docs/rules/controller-as.md" };
    schema: [];
  };
  create: (context: ESLintContext) => ESLintVisitor;
};

Deferred

Encourages using $q(function(resolve, reject){}) instead of $q.deferred.

/**
 * Use $q(function(resolve, reject){}) instead of $q.deferred
 * Promotes modern promise construction patterns
 */
const deferred = {
  meta: {
    docs: { url: "https://github.com/Gillespie59/eslint-plugin-angular/blob/master/docs/rules/deferred.md" };
    schema: [];
  };
  create: (context: ESLintContext) => ESLintVisitor;
};

Usage Example:

// ✗ BAD - Using $q.deferred
function getData() {
  var deferred = $q.defer();
  // async operation
  return deferred.promise;
}

// ✓ GOOD - Using $q constructor
function getData() {
  return $q(function(resolve, reject) {
    // async operation
  });
}

DI Unused

Disallows unused dependency injection parameters.

/**
 * Disallow unused DI parameters
 * Prevents unnecessary dependencies and keeps code clean
 */
const diUnused = {
  meta: {
    docs: { url: "https://github.com/Gillespie59/eslint-plugin-angular/blob/master/docs/rules/di-unused.md" };
    schema: [];
  };
  create: (context: ESLintContext) => ESLintVisitor;
};

Directive Restrict

Disallows directive restrict values other than 'A' or 'E'.

/**
 * Disallow any other directive restrict than 'A' or 'E'
 * Enforces consistent directive usage patterns
 * Linked to John Papa's Angular Style Guide y074
 */
const directiveRestrict = {
  meta: {
    docs: { url: "https://github.com/Gillespie59/eslint-plugin-angular/blob/master/docs/rules/directive-restrict.md" };
    schema: [{
      type: "object",
      properties: {
        restrict: { type: "string" },
        explicit: { type: "string" }
      }
    }];
  };
  create: (context: ESLintContext) => ESLintVisitor;
};

Empty Controller

Disallows empty controllers to prevent unnecessary code.

/**
 * Disallow empty controllers
 * Prevents creation of controllers with no functionality
 */
const emptyController = {
  meta: {
    docs: { url: "https://github.com/Gillespie59/eslint-plugin-angular/blob/master/docs/rules/empty-controller.md" };
    schema: [];
  };
  create: (context: ESLintContext) => ESLintVisitor;
};

No Controller

Disallows use of controllers according to the component-first pattern.

/**
 * Disallow use of controllers (according to the component first pattern)
 * Promotes component-based architecture over controller-based
 */
const noController = {
  meta: {
    docs: { url: "https://github.com/Gillespie59/eslint-plugin-angular/blob/master/docs/rules/no-controller.md" };
    schema: [];
  };
  create: (context: ESLintContext) => ESLintVisitor;
};

No Inline Template

Disallows the use of inline templates in favor of external template files.

/**
 * Disallow the use of inline templates
 * Promotes separation of concerns between HTML and JavaScript
 */
const noInlineTemplate = {
  meta: {
    docs: { url: "https://github.com/Gillespie59/eslint-plugin-angular/blob/master/docs/rules/no-inline-template.md" };
    schema: [{
      type: "object",
      properties: {
        allowSimple: { type: "boolean" }
      }
    }];
  };
  create: (context: ESLintContext) => ESLintVisitor;
};

No Run Logic

Keeps run functions clean and simple by limiting their complexity.

/**
 * Keep run functions clean and simple
 * Enforces minimal logic in Angular run blocks
 * Linked to John Papa's Angular Style Guide y171
 */
const noRunLogic = {
  meta: {
    docs: { url: "https://github.com/Gillespie59/eslint-plugin-angular/blob/master/docs/rules/no-run-logic.md" };
    schema: [];
  };
  create: (context: ESLintContext) => ESLintVisitor;
};

No Services

Disallows dependency injection of specified services for certain component types.

/**
 * Disallow DI of specified services for other angular components
 * Prevents inappropriate service usage (e.g., $http in controllers)
 */
const noServices = {
  meta: {
    docs: { url: "https://github.com/Gillespie59/eslint-plugin-angular/blob/master/docs/rules/no-services.md" };
    schema: [{
      type: "object",
      properties: {
        allow: { type: "array" },
        disallow: { type: "array" }
      }
    }];
  };
  create: (context: ESLintContext) => ESLintVisitor;
};

On Watch

Requires $on and $watch deregistration callbacks to be saved in a variable.

/**
 * Require $on and $watch deregistration callbacks to be saved in a variable
 * Prevents memory leaks by ensuring proper cleanup
 */
const onWatch = {
  meta: {
    docs: { url: "https://github.com/Gillespie59/eslint-plugin-angular/blob/master/docs/rules/on-watch.md" };
    schema: [];
  };
  create: (context: ESLintContext) => ESLintVisitor;
};

Usage Example:

// ✗ BAD - Not storing deregistration callback
$scope.$watch('value', function() {});
$scope.$on('event', function() {});

// ✓ GOOD - Storing callbacks for cleanup
var watchDeregistration = $scope.$watch('value', function() {});
var listenerDeregistration = $scope.$on('event', function() {});

$scope.$on('$destroy', function() {
  watchDeregistration();
  listenerDeregistration();
});

Prefer Component

Promotes using component() over directive() for better Angular 2 migration path.

/**
 * Prefer component over directive
 * Encourages component-based architecture for easier Angular 2+ migration
 */
const preferComponent = {
  meta: {
    docs: { url: "https://github.com/Gillespie59/eslint-plugin-angular/blob/master/docs/rules/prefer-component.md" };
    schema: [];
  };
  create: (context: ESLintContext) => ESLintVisitor;
};