# AUR4200

## Error Message

`AUR4200: Validate behavior used on non property binding`

## Description

This error occurs when the `& validate` binding behavior is used on a binding type other than property bindings. The validate binding behavior is specifically designed to work with property bindings (like `value.bind`, `checked.bind`) and cannot be used with other binding types such as event bindings, template controllers, or other binding behaviors.

## Common Scenarios

### Using Validate on Event Bindings

```html
<!-- ❌ Wrong: Validate behavior on event binding -->
<button click.trigger="save() & validate">Save</button>
<form submit.trigger="handleSubmit() & validate">
```

### Using Validate on Template Controllers

```html
<!-- ❌ Wrong: Validate behavior on template controllers -->
<div if.bind="isVisible & validate">Content</div>
<div repeat.for="item of items & validate">
```

### Using Validate on Text Content

```html
<!-- ❌ Wrong: Validate behavior on text interpolation -->
<span textcontent.bind="message & validate">Error</span>
```

### Using Validate on Class/Style Bindings

```html
<!-- ❌ Wrong: Validate behavior on class bindings -->
<div class.bind="cssClass & validate">Content</div>
<div style.bind="styles & validate">Content</div>
```

## Solutions

### 1. **Use Validate Only on Form Control Property Bindings**

```html
<!-- ✅ Correct: Validate on form control value bindings -->
<input type="text" value.bind="user.name & validate">
<input type="email" value.bind="user.email & validate">
<input type="checkbox" checked.bind="user.isActive & validate">
<select value.bind="user.country & validate">
  <option value="">Select Country</option>
  <option value="US">United States</option>
  <option value="CA">Canada</option>
</select>
```

### 2. **Use Validation Controller for Programmatic Validation**

```typescript
import { ValidationController, ValidationControllerFactory } from '@aurelia/validation-html';

export class MyComponent {
  user = { name: '', email: '' };
  
  constructor(private validationControllerFactory: ValidationControllerFactory) {
    this.validationController = validationControllerFactory.createForCurrentScope();
  }
  
  async save() {
    // ✅ Correct: Programmatic validation instead of binding behavior on events
    const result = await this.validationController.validate();
    if (result.valid) {
      // Proceed with save
      this.performSave();
    }
  }
  
  private performSave() {
    // Save logic here
  }
}
```

### 3. **Proper Template Structure with Validation**

```html
<!-- ✅ Correct: Comprehensive validation setup -->
<template>
  <form submit.trigger="save()">
    <div class="form-group">
      <label for="name">Name:</label>
      <input 
        id="name" 
        type="text" 
        value.bind="user.name & validate"
        class.bind="user.name | errorClass">
      <span class="error" if.bind="user.name | hasError">
        ${user.name | errorMessage}
      </span>
    </div>
    
    <div class="form-group">
      <label for="email">Email:</label>
      <input 
        id="email" 
        type="email" 
        value.bind="user.email & validate"
        class.bind="user.email | errorClass">
      <span class="error" if.bind="user.email | hasError">
        ${user.email | errorMessage}
      </span>
    </div>
    
    <button type="submit" disabled.bind="!isFormValid">
      Save
    </button>
  </form>
</template>
```

### 4. **Custom Validation Triggers**

```html
<!-- ✅ Correct: Validate with specific triggers -->
<input 
  type="text" 
  value.bind="user.name & validate:blur"
  placeholder="Enter your name">

<input 
  type="email" 
  value.bind="user.email & validate:change"
  placeholder="Enter your email">

<!-- ✅ Correct: Manual validation trigger -->
<input 
  type="password" 
  value.bind="user.password & validate:manual"
  placeholder="Enter password">
<button click.trigger="validatePassword()">Validate Password</button>
```

```typescript
export class MyComponent {
  
  validatePassword() {
    // Manually trigger validation for password field
    this.validationController.validateTrigger = ValidationTrigger.manual;
    this.validationController.validate({ object: this.user, propertyName: 'password' });
  }
}
```

## Example: Complete Validation Setup

```typescript
// user-form.ts
import { ValidationRules, ValidationController, ValidationControllerFactory } from '@aurelia/validation';
import { autoinject } from '@aurelia/kernel';

@autoinject
export class UserForm {
  user = { 
    name: '', 
    email: '', 
    age: null as number | null,
    isActive: false 
  };
  
  validationController: ValidationController;
  
  constructor(validationControllerFactory: ValidationControllerFactory) {
    this.validationController = validationControllerFactory.createForCurrentScope();
    this.setupValidation();
  }
  
  private setupValidation() {
    ValidationRules
      .ensure((u: typeof this.user) => u.name)
        .required()
        .minLength(2)
        .maxLength(50)
      .ensure((u: typeof this.user) => u.email)
        .required()
        .email()
      .ensure((u: typeof this.user) => u.age)
        .required()
        .min(18)
        .max(120)
      .on(this.user);
  }
  
  async save() {
    const result = await this.validationController.validate();
    if (result.valid) {
      console.log('User is valid, saving...', this.user);
      // Perform save operation
    } else {
      console.log('Validation errors:', result.results);
    }
  }
  
  get isFormValid() {
    return this.validationController.results.length === 0 ||
           this.validationController.results.every(r => r.valid);
  }
}
```

```html
<!-- user-form.html -->
<template>
  <form submit.trigger="save()">
    <!-- ✅ Correct: Validate behavior only on property bindings -->
    <input 
      type="text" 
      value.bind="user.name & validate"
      placeholder="Name">
      
    <input 
      type="email" 
      value.bind="user.email & validate"
      placeholder="Email">
      
    <input 
      type="number" 
      value.bind="user.age & validate"
      placeholder="Age">
      
    <label>
      <input 
        type="checkbox" 
        checked.bind="user.isActive & validate">
      Active User
    </label>
    
    <!-- ✅ Correct: No validate behavior on submit event -->
    <button type="submit" disabled.bind="!isFormValid">
      Save User
    </button>
  </form>
</template>
```

## Debugging Tips

1. **Check Binding Type**: Ensure `& validate` is only used on property bindings (`value.bind`, `checked.bind`, etc.)
2. **Review Template**: Look for validate behavior on event bindings or template controllers
3. **Use Validation Controller**: For complex validation scenarios, use the validation controller programmatically
4. **Validate Binding Syntax**: Make sure the binding syntax follows the correct pattern

## Related Errors

* [AUR4201](/developer-guides/error-messages/4200-to-4206/aur4201.md) - Validate binding behavior extraneous args
* [AUR4202](/developer-guides/error-messages/4200-to-4206/aur4202.md) - Validate binding behavior invalid trigger name
* [AUR4204](/developer-guides/error-messages/4200-to-4206/aur4204.md) - Validate binding behavior invalid binding target


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.aurelia.io/developer-guides/error-messages/4200-to-4206/aur4200.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
