or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdcore-components.mdindex.mdmethod-lifecycle-decorators.mdproperty-decorators.md

property-decorators.mddocs/

0

# Property Decorators

1

2

Decorators for reactive properties, props, template references, and data binding in Vue components.

3

4

## Capabilities

5

6

### Setup Decorator

7

8

Decorator for setup functions that return reactive data, integrating with Vue 3's Composition API.

9

10

```typescript { .api }

11

/**

12

* Decorator for setup functions that return reactive data

13

* @param setupFunction - Function that returns reactive data or Promise of reactive data

14

* @returns Property decorator

15

*/

16

function Setup(setupFunction: OptionSetupFunction): PropertyDecorator;

17

18

type OptionSetupFunction = (

19

props: Readonly<any>,

20

ctx: SetupContext<any>

21

) => any | Promise<any>;

22

23

interface SetupConfig {

24

setupFunction: OptionSetupFunction;

25

}

26

```

27

28

**Usage Examples:**

29

30

```typescript

31

import { Component, Setup } from "vue-facing-decorator";

32

import { ref, computed, reactive } from "vue";

33

34

@Component

35

class SetupComponent {

36

// Simple reactive reference

37

@Setup(() => ref("initial value"))

38

message!: string;

39

40

// Reactive object

41

@Setup(() => reactive({ count: 0, items: [] }))

42

state!: { count: number; items: any[] };

43

44

// Computed property

45

@Setup(() => computed(() => `Count: ${this.state.count}`))

46

displayText!: string;

47

48

// Async setup

49

@Setup(async () => {

50

const data = await fetch('/api/data');

51

return ref(await data.json());

52

})

53

asyncData!: any;

54

55

// Setup with context

56

@Setup((props, { emit, slots, attrs }) => {

57

const handleClick = () => emit('clicked');

58

return ref({ handleClick });

59

})

60

handlers!: { handleClick: () => void };

61

}

62

```

63

64

### Ref Decorator

65

66

Decorator for template references (`$refs`) with optional custom key names.

67

68

```typescript { .api }

69

/**

70

* Decorator for template references

71

* @param key - Optional custom ref key name, defaults to property name

72

* @returns Property decorator

73

*/

74

function Ref(key?: string): PropertyDecorator;

75

76

type RefConfig = null | string;

77

```

78

79

**Usage Examples:**

80

81

```typescript

82

import { Component, Ref } from "vue-facing-decorator";

83

84

@Component({

85

template: `

86

<div>

87

<input ref="inputElement" />

88

<button ref="submitBtn">Submit</button>

89

<div ref="customKey">Custom</div>

90

</div>

91

`

92

})

93

class RefComponent {

94

// Basic ref - uses property name as ref key

95

@Ref()

96

inputElement!: HTMLInputElement;

97

98

// Basic ref with different property name

99

@Ref()

100

submitBtn!: HTMLButtonElement;

101

102

// Custom ref key

103

@Ref("customKey")

104

myDiv!: HTMLDivElement;

105

106

mounted() {

107

// Access refs after component is mounted

108

this.inputElement.focus();

109

this.submitBtn.addEventListener('click', this.handleSubmit);

110

this.myDiv.style.color = 'blue';

111

}

112

113

handleSubmit() {

114

console.log('Input value:', this.inputElement.value);

115

}

116

}

117

```

118

119

### Prop Decorator

120

121

Decorator for component props with comprehensive validation and configuration options.

122

123

```typescript { .api }

124

/**

125

* Decorator for component props with validation

126

* @param config - Optional prop configuration

127

* @returns Property decorator

128

*/

129

function Prop(config?: PropsConfig): PropertyDecorator;

130

131

interface PropsConfig {

132

type?: any;

133

required?: boolean;

134

default?: any;

135

validator?(value: any): boolean;

136

}

137

```

138

139

**Usage Examples:**

140

141

```typescript

142

import { Component, Prop } from "vue-facing-decorator";

143

144

@Component

145

class PropComponent {

146

// Basic prop

147

@Prop()

148

message!: string;

149

150

// Required prop with type

151

@Prop({ type: String, required: true })

152

title!: string;

153

154

// Prop with default value

155

@Prop({ type: Number, default: 0 })

156

count!: number;

157

158

// Prop with validator

159

@Prop({

160

type: String,

161

validator: (value: string) => ['small', 'medium', 'large'].includes(value)

162

})

163

size!: 'small' | 'medium' | 'large';

164

165

// Complex prop types

166

@Prop({ type: Array, default: () => [] })

167

items!: any[];

168

169

@Prop({ type: Object, default: () => ({}) })

170

config!: Record<string, any>;

171

172

// Custom prop type

173

@Prop({

174

type: [String, Number],

175

validator: (value) => {

176

return (typeof value === 'string' && value.length > 0) ||

177

(typeof value === 'number' && value > 0);

178

}

179

})

180

id!: string | number;

181

}

182

```

183

184

### VModel Decorator

185

186

Decorator for v-model binding with two-way data flow support.

187

188

```typescript { .api }

189

/**

190

* Decorator for v-model binding

191

* @param config - Optional v-model configuration extending PropsConfig

192

* @returns Property decorator

193

*/

194

function VModel(config?: VModelConfig): PropertyDecorator;

195

196

// Alias for VModel

197

const Model: typeof VModel;

198

199

interface VModelConfig extends PropsConfig {

200

name?: string;

201

}

202

```

203

204

**Usage Examples:**

205

206

```typescript

207

import { Component, VModel } from "vue-facing-decorator";

208

209

@Component({

210

template: `

211

<div>

212

<input v-model="value" />

213

<input v-model="customModel" />

214

</div>

215

`

216

})

217

class VModelComponent {

218

// Basic v-model (uses 'modelValue' prop and 'update:modelValue' event)

219

@VModel()

220

value!: string;

221

222

// Custom v-model name

223

@VModel({ name: "customValue" })

224

customModel!: string;

225

226

// V-model with validation

227

@VModel({

228

type: String,

229

validator: (value: string) => value.length <= 100

230

})

231

limitedText!: string;

232

233

// V-model with default

234

@VModel({

235

type: Number,

236

default: 0,

237

name: "count"

238

})

239

counter!: number;

240

}

241

242

// Usage in parent component:

243

// <VModelComponent v-model="parentValue" v-model:customValue="customValue" />

244

```

245

246

### Vanilla Decorator

247

248

Decorator to preserve original class properties without transformation.

249

250

```typescript { .api }

251

/**

252

* Decorator to preserve original class properties without Vue transformation

253

* @returns Property decorator

254

*/

255

function Vanilla(): PropertyDecorator;

256

```

257

258

**Usage Examples:**

259

260

```typescript

261

import { Component, Vanilla, Setup } from "vue-facing-decorator";

262

import { ref } from "vue";

263

264

@Component

265

class VanillaComponent {

266

// This will be transformed to reactive data

267

@Setup(() => ref("reactive"))

268

reactiveProperty!: string;

269

270

// This will be preserved as-is, not transformed

271

@Vanilla()

272

staticProperty = "not reactive";

273

274

// Vanilla method - preserved as class method

275

@Vanilla()

276

utilityMethod() {

277

return "utility function";

278

}

279

280

// Regular method - becomes Vue component method

281

componentMethod() {

282

return this.reactiveProperty + " from component";

283

}

284

285

mounted() {

286

console.log(this.staticProperty); // "not reactive"

287

console.log(this.utilityMethod()); // "utility function"

288

console.log(this.componentMethod()); // "reactive from component"

289

}

290

}

291

```

292

293

## Property Transformation Rules

294

295

The property decorators follow specific transformation rules:

296

297

1. **Setup**: Properties become part of the component's setup function return

298

2. **Ref**: Properties become accessors for template refs via `$refs`

299

3. **Prop**: Properties become Vue component props with validation

300

4. **VModel**: Properties become computed properties with getter/setter for two-way binding

301

5. **Vanilla**: Properties are preserved exactly as defined in the class

302

303

**Complete Example:**

304

305

```typescript

306

import { Component, Setup, Ref, Prop, VModel, Vanilla } from "vue-facing-decorator";

307

import { ref, computed } from "vue";

308

309

@Component({

310

template: `

311

<div>

312

<h1>{{ title }}</h1>

313

<input ref="textInput" v-model="inputValue" />

314

<p>{{ computedMessage }}</p>

315

<button @click="logStatic">Log Static</button>

316

</div>

317

`

318

})

319

class CompletePropertyExample {

320

// Prop from parent

321

@Prop({ type: String, required: true })

322

title!: string;

323

324

// Two-way binding

325

@VModel()

326

inputValue!: string;

327

328

// Reactive computed property

329

@Setup(() => computed(() => `You typed: ${this.inputValue}`))

330

computedMessage!: string;

331

332

// Template ref

333

@Ref()

334

textInput!: HTMLInputElement;

335

336

// Static property (not reactive)

337

@Vanilla()

338

staticValue = "I don't change reactively";

339

340

// Method

341

logStatic() {

342

console.log(this.staticValue);

343

this.textInput.focus();

344

}

345

}

346

```