Introducing Socket Firewall: Free, Proactive Protection for Your Software Supply Chain.Learn More
Socket
Book a DemoInstallSign in
Socket

@cosider.construction/v-set

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cosider.construction/v-set

A Vue 3 directive that simplifies bidirectional data binding between parent and child components, with advanced transformations and modular architecture.

latest
Source
npmnpm
Version
2.0.23
Version published
Weekly downloads
50
177.78%
Maintainers
1
Weekly downloads
 
Created
Source

v2.0.5

Vue v-set Directive

Revolutionary two-way data binding with advanced transformations, modular architecture, and professional development tools for Vue 3.

📖 [View Full HTML Documentation](https://www.npmjs.com/package/@cosider.construction/v-set/ README.html) - Complete interactive documentation with examples and styling

Vue 3 Modular Production Ready

🚀 Why Choose v-set?

See the dramatic difference in code simplicity:

Featurev-setStandard Vue
Simple bindingv-set.name@input="$emit('update:name', $event.target.value)"
Nested objectsv-set.user.name@update:name="$emit('update:user', {...user, name: $event})"
Array updatesv-set.users[i]:user="{i}"@update:user="$emit('update:users', [...users.slice(0, i), { ...users[i], ...$event }, ...users.slice(i + 1)])"
Transformationsv-set.price$*tax$tofixed(2)Manual calculation in handler
Custom eventsv-set.name@change€modifiedMultiple separate event handlers
Math operationsv-set.count$+1@click="$emit('update:count', count + 1)"



Features
Intuitive SyntaxModular ArchitectureAdvanced Debugging
 Clean, readable syntax that makes complex data binding simple and maintainable.

 Specialized modules for maximum maintainability and tree-shaking optimization. 
 Professional logging system with call tracing, timestamps, and development tools. 
Rich TransformationsSmart DefaultsProduction Ready
 20+ built-in modifiers plus custom modifier support for any transformation need.
 Automatic handling of native elements and Vue components with intelligent defaults.
Separate dev/prod modes, performance optimized, and battle-tested architecture. 



Instalation

Install PackageImport & SetupConfigure & Mount
npm install @cosider.construction/v-set
import { vSetInstaller } from '@cosider.construction/v-set'
vSetInstaller.dev(app, modifiers)
import { createApp } from 'vue'
import { vSetInstaller } from '@cosider.construction/v-set'
const app = createApp({})

vSetInstaller.dev(app, {})
app.mount('#app')

Production Setup

import { createApp } from 'vue'
import { vSetInstaller } from '@cosider.construction/v-set'
const app = createApp({})

vSetInstaller.prod(app, {})
app.mount('#app')

Custom Setup

import { createApp } from 'vue'
import { vSetInstaller } from '@cosider.construction/v-set'
const app = createApp({})

vSetInstaller.custom(app, {
directiveName: 'set',
enableCallTracing: true,
enableDebugTracing: false,
customModifiers: {}
})
app.mount('#app')

Manual Installation

import { vSet, vSetEmit } from '@cosider.construction/v-set'
app.directive('set', vSet)
app.mixin(vSetEmit)
app.config.globalProperties.µ = {}

app.mount('#app')

code Syntax Overview

v-set.{whatToUpdate} .@{whenToUpdate} .€{whatToEmit} .${howToUpdate} ="{UpdateWith}"

SymbolPurposeExampleDescription
.What to update.name, .user.email, .items[i]Property path to update
@When to update@click, @change, @inputEvent to listen for
What to emit€modified, €changedCustom emit event
$How to transform$upper, $trim, $*taxModifiers and operations
=Update with="{index}", ="newValue"Additional values

timeline How We Got v-set Syntax

Understanding the evolution from standard Vue event handling to v-set directive syntax:

1.1 Simplest Case

Let's trace the evolution step by step:

StepCommentTransformation
1Starting with standard Vue@update:name="$emit('update:name', $event)"
2Since the default event to emit is 'update', we can remove it@update:name="$emit('name', $event)"
3Since the default event to listen is 'update' too, we can remove it@name="$emit('name', $event)"
4Since we deal with the listen event to emit it, we can remove it too@name="$emit('name')"
5Since we got the same prop name and bind name, we can omit it too@name
6Since it's a directive, we end byv-set.name

1.2 Prop ≠ Bind

When the binding name is not like the property name:

StepCommentTransformation
1Starting with@update:nom="$emit('update:name', $event)"
2Evolution - remove 'update' from emit@update:nom="$emit('name', $event)"
3Remove 'update' from listen event@nom="$emit('name', $event)"
4Remove $event parameter@nom="$emit('name')"
5Since it's a directive we end byv-set.name:nom
Why it's flipped? Because we are aiming to update the 'name' with the value from 'nom'

1.3 Event Listen ≠ Update

When the listen event is not the default 'update':

StepCommentTransformation
1Starting with@select:nom="$emit('update:name', $event)"
2Evolution - remove 'update' from emit@select:nom="$emit('name', $event)"
3Remove $event parameter@select:nom="$emit('name')"
4Since it's a directive we end byv-set.name.@select:nom
5Or if you want (alternative syntax)v-set.name:nom.@select
It's like we say: set name to the value of nom when on select

1.4 Emitted Event ≠ Update

When the emitted event is not the default 'update':

StepCommentTransformation
1Starting with@update:name="$emit('modified:name', $event)"
2Evolution - remove 'update' from listen event@name="$emit('modified:name', $event)"
3Remove $event parameter@name="$emit('modified:name')"
4Remove ':name' from emit (implied)@name="$emit('modified')"
5We shortcut $emit by €@name="€modified"
6Since it's a directive we end byv-set.name.€modified

Evolution Summary

StepStandard Vuev-set Evolution
1. Basic@update:name="$emit('update:name', $event)"v-set.name
2. Different prop@update:nom="$emit('update:name', $event)"v-set.name:nom
3. Custom listen@select:nom="$emit('update:name', $event)"v-set.name:nom.@select
4. Custom emit@update:name="$emit('modified:name', $event)"v-set.name.€modified

description Complete Syntax Reference

General Case Syntax

v-set.{whatToUpdate} .@{whenToUpdate} .€{whatToEmit} .${howToUpdate} ="{UpdateWith}"

ComponentDescriptionExample
whatToUpdateThe prop or data path to update (e.g., name, user.name, users[0].name).name, .user.name, .users[0].name
whenToUpdateThe event to listen for. Defaults to update:propName for components or element-specific events@input, @click, @update:name
whatToEmitThe event to emit. Defaults to update:propName€update:name, €modified
howToUpdateTransformation to apply to the listened or emitted value$upper, $+5, $trim
UpdateWithThe value or expression used like extra function parameters="{i}", ="newValue"

2.1 The Bind Concept

Understanding the relationship between Props and Binds:

<child :nom="name" @update:nom="$emit('update:name', $event)" />

nom is called Bind and name is prop. Why name is called prop? Because it's a prop in the component that uses child and we are binding it to child.

2.2 whatToUpdate Structure

The whatToUpdate follows the pattern: Prop.P1....Pn:Bind or Prop.P1....Pn

In the simplest case: Prop:Bind or just Prop when Prop === Bind

ExampleExplanationEmitted Update
<input :value="form.user.name" v-set.form.user.name />Update nested object propertySend update form with new value of name
<input :value="names[i]" v-set.names[i] />Update array elementSend update names with new value of names[i]

2.3 whenToUpdate

This part should start with @ to keep the Vue world. We listen to 'event:Bind'.

ContextDefault BehaviorExample
ComponentsListen to update:bind by default<comp :nom="name" v-set.name:nom />
Native ElementsListen to default events (input, change, select)<input :value="name" v-set.name />
Path TransformationFor native elements: e.target.value@event:Bind.pathToTheValue

2.4 whatToEmit

The event name we want to emit. By default update:prop where prop is the first part of whatToUpdate.

Format: event:Prop where event can be update, select, or whatever you like.

2.5 howToUpdate and UpdateWith

Value transformation and wrapping process:

2.5.1 Value Wrapping

Why do we need wrapping? When updating nested properties or array elements, we can't just emit the new value directly. We need to preserve the immutability principle and create new objects/arrays with the updated values. This is where wrapping comes in - it automatically handles the complex object/array reconstruction for you.

Value Processing Flow
value = vListen

      ↓

value = path(value)

      ↓

value = wrapper(value)

      ↓

emit(value)
PatternListened ValueEmitted ValueWhy Wrapping is Needed
v-set.user.name$value{...user, name: $value}Preserve other user properties while updating name
v-set.users[i].name="{i}"$event[...users.slice(0,i), {...users[i], name: $event}, ...users.slice(i+1)]Maintain array immutability while updating specific element

2.5.2 Mutators: The Complete Transformation System

How Vue Uses Modifiers

In standard Vue, modifiers are simple flags like v-model.trim or @click.prevent. They provide basic transformations but are limited in scope.

Our Enhanced System

The $ symbol is used to detect the transformation part of the directive. As Vue uses modifiers separated by ., we use something similar, but it's not modifiers - it's mutators.

Why "Mutators"?

modifier + operator → mod_ifier + oper_ator → modator → motator → mutator 😊
TypePurposeSyntaxExample
ModifiersFunction-based transformations.functionName.upper, .max(x,y,2), .random(())
OperatorsMathematical/Object operations.operator var, .var operator.+1, .v*
MutatorsCombined modifiers + operators.operator modifier.+max(7)

Value Processing Pipeline

Complete Value Transformation Flow

value = vListen

      ↓

value = path(value)

      ↓

value = mutators(value) 🔄 m1→m2→m3...

      ↓

value = wrapper(value)

      ↓

value = mutators(value) 🔄 m4→m5→m6...

      ↓

emit(value)

Mutators Lifecycle

Understanding how multiple mutators are chained together:

mutators(value) = mutator1.mutator2.mutator3...mutatorN(value)

Example: $trim.upper.max(25)

value = trim(value)    // mutator1

value = upper(value)   // mutator2

value = max(value, 25) // mutator3

How We Got Mutator Syntax

Understanding the transformation from verbose processing to mathematical notation:

StepVerbose ProcessingMathematical Notation
$value = path(value)v0 = $
value = mutator1_1(value) ... value = mutator1_n(value)v1 = mutator1_1(v0) = v0.m1_1 ... v1 = $.m1_1...m1_n
value = wrapper(value)v2 = wrapper(v1) = w(v1) = $$(v0.m1_1...m1_n) = $.m1_1...m1_n.$$
value = mutator2_1(value) ... value = mutator2_n(value)v3 = mutator2(v2) = v2.mutator2 = $.m1_1...m1_n.$$.m2_1...m2_n
Final syntax with $ prefix to detect transformations$.m1_1...m1_n.$$.m2_1...m2_n
$.µBeforWarping.$$.µAfterWarping

you van also use µ/µµ instead of $/$$ to mark begin of mutators

2.5.3 Operators

Mathematical and logical operations on values:

PatternSyntaxResult
token operator.+xvalue = value + x
operator token.x%value = x / value (% used as /)
token only.xvalue = x
special cases.++value = value + 1
special cases.!value = ! value
object proprety.proprety:{...value,proprety:v} v is taking from updateWithPart/compoenent
object proprety.~obj{...value,...obj} obj is found in the updateWithPart/component

2.5.4 Modifiers

Built-in function-based transformations for common operations:

ModifierSyntaxResultExample
trim$trimRemove whitespace" hello " → "hello"
upper$upperConvert to uppercase"hello" → "HELLO"
lower$lowerConvert to lowercase"HELLO" → "hello"
toNumber$toNumberConvert to number"123" → 123
toString$toStringConvert to string123 → "123"
reverse$reverseReverse string/array"hello" → "olleh"

Note: You can also access modifiers in component methods using this..modifierName (e.g., this.µ.trim(value)).

Double Parentheses - No Auto Value Injection

Important Feature: unLike Vue modifiers, you can use double parentheses (())to prevent automatic value injection. This is crucial when you want the modifier to work without the current value being passed as a parameter.

SyntaxBehaviorExample
modifierAuto-inject current value:$vtrimtrim($v)
modifierAuto-inject current value:$vmaxmax(i,j)max($v,i,j)
modifier(())No injectiongetTimestamp(())getTimestamp()
modifiernoinjectmax((i,j))max(i,j)

2.5.5 Custom Modifiers

You can extend the system with your own transformations. There is a list of defined modifiers, but you can add your own globally or locally by calling methods of your component or using arrow functions defined in the directive's UpdateWith.

ScopeHow to DefineExample
GlobalAdd to global modifiers registryapp.config.globalProperties.µ.myModifier = (v) => v.toUpperCase()
ComponentDefine as component methodmethods: { myModifier(value) { return value.trim() } }
LocalArrow function in UpdateWith="myModifier: (v) => v.toLowerCase()"

folder ./modifiers/custom-modifiers.js

export const customModifiers = {
  // Currency formatting
  currency: (value) => '$'+Number(value).toFixed(2),
  euro: (value) => '€'+Number(value).toFixed(2),

  // Text transformations
  percentage: (value) => (Number(value) \* 100).toFixed(1)+'%',
  slugify: (str) => str.toLowerCase().replace(/\\s+/g, '-'),
  capitalize: (str) => str.charAt(0).toUpperCase() + str.slice(1),

  // Phone formatting
  phone: (str) => str.replace(/(\\d{3})(\\d{3})(\\d{4})/, '($1) $2-$3'),

  // Date formatting
  dateShort: (date) => new Date(date).toLocaleDateString(),
  timestamp: () => Date.now()
};

build Updated Setup Code

import { createApp } from 'vue'
import { vSetInstaller } from '@cosider.construction/v-set'
import { customModifiers } from './modifiers/custom-modifiers.js'
const app = createApp({})
vSetInstaller.dev(app, customModifiers)
app.mount('#app')

💡 Benefits:

  • Clean separation - Keep modifiers organized in separate files
  • Reusable - Import the same modifiers across multiple projects
  • Maintainable - Easy to add, remove, or modify custom transformations
  • Testable - Unit test your custom modifiers independently

2.5.6 UpdateWith

Why do we need UpdateWith? Vue has limitations that v-set solves:

  • v-for context access: Vue doesn't allow directives to access v-for loop variables directly
  • Arrow function definitions: You can't define inline functions in standard Vue directives
  • Dynamic parameters: Need to pass runtime values to transformations
Use CaseExampleExplanation
v-for context<comp v-for="(user,i) in users" v-set.users[i]="i" />Pass loop variable 'i' to directive since Vue doesn't provide it
Arrow functions<button v-set.cpt@click.$f(()) ="f:()=>{cpt+1}" />Define custom transformation without value injection
Value injection<button v-set.cpt@click.µ.f ="f:(v)=>{cpt+1}" />Arrow function with value parameter (though not used in this example)
Multiple variablesv-set.data.+x.-y="{x: valueX, y: valueY}"Pass object with multiple runtime values

Resolution Priority

When v-set looks for a function or modifier, it checks in this order:

  • UpdateWith definitions - Functions defined in the directive value
  • Component methods - Methods defined in the current component
  • User global modifiers - Custom modifiers added globally
  • Built-in modifiers - Default v-set transformations

integration_instructions Usage Examples

Basic Input Binding

Simple Binding

<input :value="name" v-set.name />
Simple Binding Lifecycle

Direct value assignment without wrapping:

StepProcessValue
Listen to input event<input v-set.name />
Extract value from pathevent.target.value
No mutators appliedvalue
No wrapper neededvalue (direct assignment)
Emit final value$emit('update:name', value)

With Transformations

<input :value="name" v-set.name.$.upper.trim />
With Transformations Lifecycle

Value transformation before wrapping:

StepProcessValue
Listen to input event<input v-set.name.$.upper.trim />
Extract value from pathevent.target.value
Apply mutators chaintrim(upper(value))
No wrapper neededmutatedValue (direct assignment)
Emit final value$emit('update:name', mutatedValue)

Mathematical Operations

Tax Calculator

HT: <input :value="ht" v-set.ht />

TTC: <input :value="ht \* tax" v-set.ht.$.%tax />
Tax Calculator Lifecycle

Value transformation with mathematical operators:

StepProcessValue
Listen to input event<input v-set.ht.$.%tax />
Extract value from pathevent.target.value
Apply mathematical operatorvalue / tax (% used as division)
No wrapper neededcalculatedValue (direct assignment)
Emit final value$emit('update:ht', calculatedValue)

Counter Operations

<button v-set.count.$.count.+1\>+1</button>

<button v-set.count.$.count.-1\>-1</button>

<button v-set.count.$.count.\*2\>×2</button>
Counter Operations Lifecycle

Simple mathematical operations on click events:

StepProcessValue
Listen to click event<button v-set.count.$.count.+1 />
No path extraction neededclickEvent (not used)
init value with count<button v-set.count.$.count.+1 />
Apply mathematical operator<button v-set.count.$.count.+1 />
No wrapper neededincrementedValue (direct assignment)
Emit final value$emit('update:count', count+1)

No Auto-Injection with Double Parentheses

<button v-set.date$.now(())>Set Current Time

No Auto-Injection Lifecycle

Using double parentheses to prevent automatic value injection:

StepProcessValue
Listen to click event<button v-set.date.$.now(()) />
No path extraction neededclickEvent (not used)
Call modifier without value injectionnow(()) (no parameters passed)
No wrapper neededdate (direct assignment)
Emit final value$emit('update:date', now())

Array Operations

Array Element Update

<User v-for="(user, i) in users" :user="users[i]" v-set.users[i]:user="i" />
Array Element Update Lifecycle

Array wrapping with immutable slice operations:

StepProcessValue
Listen to update event<User v-set.users[i]:user="{i}" />
Extract value from event$event (user object)
No mutators appliedvalue
Apply array wrapper[...users.slice(0,i), value, ...users.slice(i+1)]
Emit wrapped array$emit('update:users', wrappedArray)

Array Push

<button v-set.todos$push(newTodo())>Add Todo</button>
Array Push Lifecycle

Array push operation with immutable array creation:

StepProcessValue
Listen to click event<button v-set.todos$push(newTodo()) />
Get UpdateWith valuenewTodo
Apply push mutator[...todos, newTodo]
No wrapper needednewArray (direct assignment)
Emit final array$emit('update:todos', newArray)

Nested Object Operations

User Name Property

<input :value="user.name" v-set.user.name />
User Name Property Lifecycle

Object wrapping to preserve immutability:

StepProcessValue
Listen to input event<input v-set.user.name />
Extract value from pathevent.target.value
No mutators appliedvalue
Apply object wrapper{...user, name: value}
Emit wrapped object$emit('update:user', wrappedUser)

Deep Nested Property

<input :value="form.user.profile.bio" v-set.form.user.profile.bio />
Deep Nested Property Lifecycle

Deep object wrapping to preserve immutability:

StepProcessValue
Listen to input event<input v-set.form.user.profile.bio />
Extract value from pathevent.target.value
No mutators appliedvalue
Apply deep object wrapper{...form, user: {...form.user, profile: {...form.user.profile, bio: value}}}
Emit wrapped object$emit('update:form', wrappedForm)

Custom Events

Custom Listen Event

<Child v-set.name@change />
Custom Listen Event Lifecycle

Listening to custom event instead of default update:

StepProcessValue
Listen to change event<Child v-set.name@change />
Extract value from event$event
No mutators appliedvalue
No wrapper neededvalue (direct assignment)
Emit default event$emit('update:name', value)

Custom Emit Event

<Child v-set.name€modified />
Custom Emit Event Lifecycle

Emitting custom event instead of default update:

StepProcessValue
Listen to default event<Child v-set.name€modified />
Extract value from event$event
No mutators appliedvalue
No wrapper neededvalue (direct assignment)
Emit custom event$emit('modified:name', value)

Both Custom Events

<Child v-set.name@change€modified />
Both Custom Events Lifecycle

Custom listen and emit events:

StepProcessValue
Listen to change event<Child v-set.name@change€modified />
Extract value from event$event
No mutators appliedvalue
No wrapper neededvalue (direct assignment)
Emit custom event$emit('modified:name', value)

tune Built-in Modifiers

String Modifiers

ModifierDescription
upperConvert to UPPERCASE
UpperCapitalize first letter
lowerConvert to lowercase
trimRemove whitespace
replace(old,new)Replace text
replaceAll(old,new)Replace all occurrences
split(',')Split into array

Number Modifiers

ModifierDescription
parseintConvert to integer
parsefloatConvert to float
roundRound to nearest integer
ceilRound up
floorRound down
absAbsolute value
tofixed(2)Format to 2 decimals
minGet minimum value
maxGet maximum value

Array Modifiers

ModifierDescription
push(item)Add item to end
popRemove last item
shiftRemove first item
unshift(item)Add item to beginning
join('-')Join with separator

Math Operations

OperationDescription
$+5Add 5 to value
$-1Subtract 1 from value
$*taxMultiply by tax variable
$%taxDivide by tax variable (% used as /)
$++Increment by 1
$--Decrement by 1

bug_report Development & Debugging

Enable Logging

// Enable call tracing (shows function calls with timestamps) this.$vSetInstaller.configureLogging({ enableCalls: true, enableTrace: true }); // Or use vLog directly this.$vLog.enableCalls().enableTrace();

Debug Output Example

🔧 [14:23:45.123] vSet.mounted 🔧 [14:23:45.124] vSetConf.get 🔧 [14:23:45.125] vSetConf.getDomInfo 🔧 [14:23:45.126] vSetDom.listen

Ready to Transform Your Vue Development?

Join thousands of developers who have already upgraded their Vue applications with v-set.

NPM Package 📖 HTML Documentation View Examples API Documentation

Made with ❤️ by Cosider Construction Transform your Vue development experience with the power of v-set!

Keywords

vue

FAQs

Package last updated on 09 Sep 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts