or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ajax-remote.mdcsrf-protection.mddom-utilities.mdelement-state.mdevent-system.mdfeature-handlers.mdform-handling.mdindex.md

element-state.mddocs/

0

# Element State Management

1

2

System for enabling and disabling form elements and links during processing, providing visual feedback to users and preventing double-submission issues.

3

4

## Capabilities

5

6

### Element Disabling

7

8

Disables elements and provides visual feedback during processing.

9

10

```javascript { .api }

11

/**

12

* Disable element and show loading state

13

* @param element - Element or Event containing target element to disable

14

*/

15

function disableElement(element: Element | Event): void;

16

```

17

18

**Usage Examples:**

19

20

```javascript

21

// Disable a button

22

const button = document.querySelector("#submit-btn");

23

Rails.disableElement(button);

24

25

// Disable during event handling

26

document.addEventListener("click", function(event) {

27

if (event.target.matches("[data-disable-with]")) {

28

Rails.disableElement(event);

29

}

30

});

31

32

// Works with different element types

33

const link = document.querySelector('a[data-disable-with="Processing..."]');

34

Rails.disableElement(link);

35

```

36

37

### Element Enabling

38

39

Re-enables elements and restores their original content.

40

41

```javascript { .api }

42

/**

43

* Re-enable element and restore original content

44

* @param element - Element or Event containing target element to enable

45

*/

46

function enableElement(element: Element | Event): void;

47

```

48

49

**Usage Examples:**

50

51

```javascript

52

// Re-enable a button

53

const button = document.querySelector("#submit-btn");

54

Rails.enableElement(button);

55

56

// Enable after AJAX completion

57

Rails.ajax({

58

type: "POST",

59

url: "/api/data",

60

beforeSend: () => Rails.disableElement(submitButton),

61

complete: () => Rails.enableElement(submitButton)

62

});

63

64

// Enable elements after page show (browser back/forward)

65

window.addEventListener("pageshow", function() {

66

Rails.$("[data-disable-with]:disabled").forEach(Rails.enableElement);

67

});

68

```

69

70

### Disabled Element Handler

71

72

Prevents actions on disabled elements by stopping event propagation.

73

74

```javascript { .api }

75

/**

76

* Handle clicks on disabled elements by stopping all events

77

* @param event - Event to handle (typically click event)

78

*/

79

function handleDisabledElement(event: Event): void;

80

```

81

82

**Usage Examples:**

83

84

```javascript

85

// Automatically prevent actions on disabled elements

86

document.addEventListener("click", Rails.handleDisabledElement);

87

88

// Manual usage in custom event handlers

89

button.addEventListener("click", function(event) {

90

if (this.disabled) {

91

Rails.handleDisabledElement(event); // Stops everything

92

return;

93

}

94

// Normal click handling

95

});

96

```

97

98

## Data Attribute Integration

99

100

Elements are automatically managed based on data attributes:

101

102

### data-disable-with

103

104

Replaces element content with loading text during processing:

105

106

```html

107

<!-- Button shows "Creating..." when clicked -->

108

<button type="submit" data-disable-with="Creating...">Create Post</button>

109

110

<!-- Link shows "Loading..." when clicked -->

111

<a href="/posts/1" data-remote="true" data-disable-with="Loading...">View Post</a>

112

113

<!-- Input shows loading text in value -->

114

<input type="submit" value="Save" data-disable-with="Saving..." />

115

```

116

117

### data-disable

118

119

Disables element without changing its content:

120

121

```html

122

<!-- Button becomes disabled but keeps original text -->

123

<button type="submit" data-disable="true">Submit</button>

124

125

<!-- Link becomes disabled and click events are prevented -->

126

<a href="/posts/1" data-method="delete" data-disable="true">Delete</a>

127

```

128

129

## Element-Specific Behavior

130

131

### Form Elements (Buttons, Inputs)

132

133

```javascript

134

// Button content replacement

135

<button data-disable-with="Processing...">Submit</button>

136

// Becomes: <button disabled>Processing...</button>

137

138

// Input value replacement

139

<input type="submit" value="Save" data-disable-with="Saving..." />

140

// Becomes: <input type="submit" value="Saving..." disabled />

141

```

142

143

### Links

144

145

```javascript

146

// Link content replacement and click prevention

147

<a href="/posts" data-disable-with="Loading...">Posts</a>

148

// Becomes: <a href="/posts">Loading...</a> (with click handler to stop events)

149

```

150

151

### Forms

152

153

Entire forms can be disabled during submission:

154

155

```html

156

<form data-remote="true">

157

<input type="text" data-disable-with="Processing..." />

158

<button type="submit" data-disable-with="Submitting...">Submit</button>

159

</form>

160

```

161

162

## Automatic Integration

163

164

Rails UJS automatically manages element states during:

165

166

- **Form submission**: Disables all form elements with disable attributes

167

- **AJAX requests**: Disables trigger elements during request lifecycle

168

- **Page navigation**: Re-enables elements when returning via browser history

169

- **Remote forms**: Manages submit button states during AJAX form processing

170

171

## Selectors Used

172

173

Rails UJS uses these selectors to identify elements for state management:

174

175

```javascript { .api }

176

// Elements that can be disabled during form submission

177

const formDisableSelector = "input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled";

178

179

// Elements that can be re-enabled after processing

180

const formEnableSelector = "input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled";

181

182

// Links that can be disabled

183

const linkDisableSelector = "a[data-disable-with], a[data-disable]";

184

185

// Buttons that can be disabled

186

const buttonDisableSelector = "button[data-remote][data-disable-with], button[data-remote][data-disable]";

187

```

188

189

## State Management Lifecycle

190

191

1. **Initial State**: Elements are enabled with original content

192

2. **Trigger Event**: User clicks/submits element with disable attributes

193

3. **Disable Phase**: Element is disabled, content replaced if `data-disable-with` present

194

4. **Processing**: Element remains disabled during AJAX request or form submission

195

5. **Completion**: Element is re-enabled, original content restored

196

6. **Error Handling**: Element is re-enabled even on errors to prevent permanent lock

197

198

## Content Editable Support

199

200

The system automatically skips content editable elements to prevent interference with rich text editors:

201

202

```javascript

203

// Content editable elements are never disabled

204

<div contenteditable="true" data-disable-with="Processing...">

205

Rich text content...

206

</div>

207

```