Demo on http://juai.hldks.net
Put this CDN link into the head of your website
<script src="http://cdn.hldks.net/js/juai.min.js"></script>HTML
<body>
<div id="#app">
{{ msg }}
</div>
</body>JS
class App {
msg = 'Hello Juai!'
}
Juai('#app', App)As you can see, this code shares some features from Angular and Vue. The feature from angular is that you can write your application as a class where every property is reactive state which can be used in your template and the feature from Vue is that it is very lightweight and easy to use. The only thing we had to done was to call a function Juai and pass element and class as arguments
Juai allows you to bind a property to an input element (including select and textarea) so whenever the value in input changes, the new value will be saved in the state to which element is bound to
<p>Your username is {{ username }}</p>
<input type="text" bind:username>
<p>Your age is {{ range }}</p>
<input type="range" bind:range>
<p>Do you agree ? {{ checked ? 'yes' : 'no' }}</p>
<input type="checkbox" bind:checked>
<p>Please select your vehicle. {{ vehicle }}</p>
<select bind:vehicle>
<option value="car">Car</option>
<option value="train">Train</option>
</select>class App {
username = ''
range = 0
checked = false
vehicle = ''
}If you want to bind an element to value which's name is written in camelCase, you have to write the name of the state in dash-case since HTML is by default using lowercase attributes
<p>{{ mySuperSecretPassword }}</p>
<input type="text" bind:my-super-secret-password>class App {
mySuperSecretPassword = ''
}Let's say that you want to change attribute of some element dynamically (based on some state for example). To achieve that, you have to add dynamic: keyword infront of the attribute. When added, the value of attribute will be evaluated as JavaScript expression within your App context
<input dynamic:type="isPasswordVisible ? 'text' : 'password'">
<input type="checkbox" bind:is-password-visible>You can also make dynamic attribute's value to be a result of a function
<input dynamic:type="inputType()">
<input type="checkbox" bind:is-password-visible>class App {
isPasswordVisible = false
inputType() {
return this.isPasswordVisible ? 'text' : 'password'
}
}To add an event listener to element, the only thing you have to do is to add keyword on: following the actual event you want to listen to.
<button on:click="count++">You clicked {{ count }} times</button>class App {
count = 0
}Another example
<div
style="height: 50px; width: 50px; background: red"
on:touchstart="touchStart"
on:touchend="touchEnd">{{ isTouching }}</div>class App {
isTouching = false
touchStart(event) {
this.isTouching = true
console.log(event)
}
touchEnd() {
this.isTouching = false
}
}The second example is showing the second way you can listen to an event. You can just simply add name of your function in your App as a attribute value and whenever the event occurs, your function will be executed with default event data passed in as an argument
Juai allows you to conditionally toggle certain css classes. To achieve that, add to your element keyword class: following the name of the class. Let's take the second example from events category and take it to the next level!
.green {
background: green;
}<div
style="height: 50px; width: 50px; background: red"
class:green="isTouching"
on:touchstart="isTouching = true"
on:touchend="isTouching = false">{{ isTouching }}</div>class App {
isTouching = false
}Keep in mind that currently, with this approach you can't use css class names which are written in camelCase
There are few ways how you can style an element dynamically. The syntax of doing it, is simple. You just add keyword style: infront of the style property you want to make dynamic and as a value you pass JavaScript expression
<span style:color="'red'">Hello</span>
<span style:color="fontColor">Hello</span>
<span style:border="${borderWidth}px solid red">Hello</span>Don't be confused with second and third line of this example. The attributes value will be evaluated as JavaScript expression as long as it is not written in template string style. In that case, the value will be evaluated as string
class App {
fontColor = 'cyan'
borderWidth = 20
}<div
style:width="${width}px"
style:height="${height}px"
style:background="color"></div>
<input type="range" bind:width min="100" max="300">
<input type="range" bind:height min="100" max="300">
<input type="color" bind:color>class App {
width = 100
height = 100
color = 'black'
}If (for some unknown reason) you want to conditionally toggle actual styles, you can do so by following this syntax:
style:<style property>:<style value>="<condition>"
style:<style property>:<style value> // Style will be just simply added
Example
<span style:color:red="isSomethingTrue()">Hello</span>
<span style:color:green>Hello</span>
<span style:border:2px.solid.yellow="isSomethingTrue()">Hello</span>
<span style:border:6px.solid.red>Hello</span>Keep in mind that if you want to add multiple values you have to separate them with dot. The dot acts like space in css
This useless feature also doesn't support values which are comma separated (multiple transitions for example)
Very simple feature which allows you to conditionally show or hide some element.
<p is:visible="password.length > 10">Your password is very strong</p>
<p is:hidden="password.length < 11">Your password is very not strong</p>
<input type="password" bind:password>class App {
password = ''
}The is:visible and is:hidden are basically same things, the only difference is that the expression in is:hidden will be negated. Same applies for directives is:enabled and is:disabled.
- Add some kind of
v-fororng-forequivalent - Add component support
Make two-way binding work properlyArray aren't reactive :( gonna fix ASAP- ¯\(ツ)/¯