<aside> βΉοΈ This mini framework aims to explain by example the basics of:

<aside>
βΉοΈ Everytime we start the practical lesson the first thing you need to do is to create a new folder and clone the project repository into it with the console command e.g. git clone <https://github.com/jk-oster/kwm-example.git>.
After each practical lesson you have a week ποΈ to complete the steps for the lesson and hand them in via Moodle.
</aside>
<aside>
π‘ Copy the repository to your PC with git clone <https://github.com/jk-oster/lesson-1.git>. Navigate into the project folder lesson-1 and start the development server with npx vite β click the link of the command output to open the development page.
</aside>
<aside>
π‘ Copy the repository to your PC with git clone <https://github.com/jk-oster/lesson-2.git>. Navigate into the project folder lesson-2 and start the development server with npx vite β click the link of the command output to open the development page.
</aside>
<aside>
π‘ Copy the repository to your PC with git clone <https://github.com/jk-oster/lesson-3.git>. Navigate into the project folder lesson-3 and start the development server with npx vite β click the link of the command output to open the development page.
</aside>
observable & computed β "Synchroniserte Variablen" / "Reaktive Variablen"
on('<eventName>', () => action()) β Click Listener registrieren (UI β Data)
<attributName>="${value}" β HTML Attribute mit Observable synchronisieren (DataβUI)
bind(observable) β Input-Daten mit Observable synchronisieren (DataβUI & UIβData)
import { Component, html, observable, on, bind } from "../../kwm-js";
export class ExampleComponent extends Component {
// 1. Event listener - use on() helper
doSomething = () => console.log('something');
// 2. Input value binding - use observable() and bind()
inputData = observable('Some initial text');
// 3. Conditional visibility - use observable()
isHidden = observable(false);
// 4. Example todo for conditional classes
todo = observable({ completed: false });
render() {
return html`
<!-- 1. Event listener - use on() helper directly in template -->
<button ${on('click', this.doSomething)}>Click me</button>
<!-- 2. Input value binding - use bind() for two-way data binding -->
<input type="text" ${bind(this.inputData)} />
<!-- 3. Conditional visibility - use template interpolation with .value -->
${!this.isHidden.value && html`<div>This element is visible</div>`}
<!-- Alternative: Always render but toggle hidden attribute -->
<div ?hidden="${this.isHidden.value}">Toggleable content</div>
<!-- 4. Text content binding - use template interpolation -->
<div>${this.inputData.value}</div>
<!-- 5. Conditional classes - use template expressions -->
<div class="${this.todo.value.completed && 'text-line-through'}">
Conditional class example
</div>
<!-- Conditional inline styles -->
<div style="${this.todo.value.completed && 'text-decoration: line-through;'}">
Conditional style example
</div>
<!-- Direct value as class (if inputData contains class name) -->
<div class="${this.inputData.value}">
Class from inputData
</div>
<!-- 6. Image src binding - use template interpolation -->
<img src="${this.inputData.value}" alt="Dynamic image" />
<!-- Use bind() for two-way binding (if editable) -->
<input ${bind(this.inputData)} />
`;
}
}
customElements.define('example-component', ExampleComponent);
| Feature | kwmJS | Angular | React | Vue.js |
|---|---|---|---|---|
| Conditional Rendering | ${condition && '<component />'} |
<component *ngIf="condition" /> |
{condition && <Component />} |
<component v-if="condition" /> |
| Loop / List Rendering | ${items.map(item => '<component id="${item.id}" />')} |
<component ngFor="let item of items" [id]="item.id" /> |
{items.map(item => <Component key={item.id}>)} |
<component-for="item in items" :key="item.id" /> |
| One-way Attribute Binding (DataβUI) | attributename="${this.value}" |
[attributename]="value" |
attributename={value} |
:attributename="value" |
| Two-way Binding (DataβUI & UIβData) | bind(this.obsVariable) |
[(ngModel)]="property" |
value={property} onChange={e => setProperty(e.target.value)} |
v-model="property" |
| Event Binding | on("click", method) |
(click)="method()" |
onClick={method()} |
@click="method()" |
| Declaring Reactive Variable | this.num = observable(1) |
this.num = signal(1) |
const [num, setNum] = useState(1) |
const num = ref(1) |
|---|
| Computed values | this.text = computed(()=> 'Result ' + this.obs.value + this.otherObs.value) |
this.text = computed(() => 'Result ' + this.someSignal() + this.someOtherSignal()) |
const text = useMemo(() => 'Result ' + someValue + someOtherValue, [someValue, someOtherValue]) |
const text = compute(()=>'Result ' + someRefValue.value + someOtherRefValue.value) |
|---|
Some terms in programming are confusing and there are often various expression that mean the same or a similar thing. So here is a quick overview of the most important ones: