2020-04-23

Svelte Tutorial 5: Events (English & Indonesia)

English


Events


As we've briefly seen already, you can listen to any event on an element with the on: directive:

<script>
let m = { x: 0, y: 0 };

function handleMousemove(event) {
m.x = event.clientX;
m.y = event.clientY;
}
</script>

<style>
div { width: 100%; height: 100%; }
</style>

<div on:mousemove={handleMousemove}>
The mouse position is {m.x} x {m.y}
</div>

See this list for list of all events available on the DOM.

Inline Handlers


You can also declare event handlers inline:

<div on:mousemove="{e => m = { x: e.clientX, y: e.clientY }}">
The mouse position is {m.x} x {m.y}
</div>

The quote marks are optional, but they're helpful for syntax highlighting in some environments.

Event Modifiers


DOM event handlers can have modifiers that alter their behaviour. For example, a handler with a once modifier will only run a single time:

<script>
function handleClick(e) { // you can access the event and event.target
alert('no more alerts')
}
</script>

<button on:click|once={handleClick}>
Click me
</button>

The full list of modifiers:
  • preventDefault — calls event.preventDefault() before running the handler. Useful for client-side form handling.
  • stopPropagation — calls event.stopPropagation(), preventing the event reaching the next element
  • passive — improves scrolling performance on touch/wheel events (Svelte will add it automatically where it's safe to do so)
  • capture — fires the handler during the capture phase instead of the bubbling phase
  • once — remove the handler after the first time it runs
  • self — only trigger handler if event.target is the element itself
You can chain modifiers together, e.g. on:click|once|capture={...}.

Component Events


Components can also dispatch events. To do so, they must create an event dispatcher. This event is custom made by you, so you can use any name for event name, in this example we use 'message' for event name. createEventDispatcher must be called when the component is first instantiated — you can't do it later inside e.g. a setTimeout callback. This links dispatch to the component instance.

<script>
 // Inner.svelte

import { createEventDispatcher } from 'svelte';

const dispatch = createEventDispatcher();

function sayHello() {
dispatch('message', {
text: 'Hello!'
});
}
</script>

After that we can use the component in our main app. We can alert text we got from component, that is contained in event.detail. Notice the event name in Inner component is 'message', you can use any name it's not predefined name.

<script>
import Inner from './Inner.svelte';

function handleMessage(event) {
alert(event.detail.text); // Hello! from Inner.svelte
}
</script>

<Inner on:message={handleMessage}/>

Event Forwarding


Unlike DOM events, component events don't bubble. If you want to listen to an event on some deeply nested component, the intermediate components must forward the event. For example we have App.svelte for main app, Inner.svelte and Outer.svelte for component will be used in main app. Outer will contain Inner component (App <- Outer <- Inner). When Inner dispatch event, event cannot be used in main app, unless we do event forwarding in Outer component. This is example of event forwarding in Outer.svelte. Notice the <Inner on:message/> instead of just <Inner/>

<script>
import Inner from './Inner.svelte';
</script>

<Inner on:message/>

DOM Event Forwarding


Event forwarding works for DOM events too. For example if we made custom button like this

<style>
button {
height: 4rem;
width: 8rem;
background-color: #aaa;
border-color: #f1c40f;
color: #f1c40f;
font-size: 1.25rem;
background-image: linear-gradient(45deg, #f1c40f 50%, transparent 50%);
background-position: 100%;
background-size: 400%;
transition: background 300ms ease-in-out;
}
button:hover {
background-position: 0;
color: #aaa;
}
</style>

<button>Click me</button>

Then we use custom button in main app

<script>
import CustomButton from './CustomButton.svelte';

function handleClick() {
alert('clicked');
}
</script>

<CustomButton on:click={handleClick}/>

This wont work, as you notice in CustomButton.svelte we haven't added event forwarding yet, so instead of using just  <button>Click me</button>, we need to type <button on:click>Click me</button> as event forwarding.




Indonesia


Events


Seperti yang sudah kita lihat sebelumnya, kita bisa menangkap even apapun di elemen apapun dengan menggunakan direktif on: :

<script>
let m = { x: 0, y: 0 };

function handleMousemove(event) {
m.x = event.clientX;
m.y = event.clientY;
}
</script>

<style>
div { width: 100%; height: 100%; }
</style>

<div on:mousemove={handleMousemove}>
The mouse position is {m.x} x {m.y}
</div>

Lihat daftar ini untuk mengetahui semua even yang ada pada DOM.

Inline Handlers


Kita juga bisa deklarasi event handler langsung di dalam tag:

<div on:mousemove="{e => m = { x: e.clientX, y: e.clientY }}">
The mouse position is {m.x} x {m.y}
</div>

Tanda petik dua opsional, tapi bisa berguna untuk tampilan sintaks pada environment tertentu.

Event Modifiers


Event handler DOM bisa memiliki modifier yang mengubah kelakuan mereka, contoh nya handler dengan modifier once hanya akan dijalankan sekali saja:

<script>
function handleClick(e) { // you can access the event and event.target
alert('no more alerts')
}
</script>

<button on:click|once={handleClick}>
Click me
</button>

Daftar lengkap modifier:
  • preventDefault — memanggil event.preventDefault() sebelum menjalankan handler, berguna untuk pengaturan form di sisi client.
  • stopPropagation — memanggil event.stopPropagation(), mencegah event mencapai elemen berikutnya.
  • passive — meningkatkan performa scroll pada event touchpad/wheel mouse (svelte akan menambahkan secara otomatis ketika dirasa aman).
  • capture — memicu handler selama fase capture daripada fase bubble.
  • once — menghilangkan handler sesudah dijalankan satu kali.
  • self — hanya menjalankan handler jika  only trigger handler if event.target adalah element itu sendiri
Kita bisa menggabungkan beberapa modifiers sekaligus, contohnya on:click|once|capture={...}.

Component Events


Komponen juga bisa melakukan dispatch even. Untuk melakukan nya, komponen harus dibuatkan event dispatcher. Kita harus membuat even ini sendiri, jadi kita bisa menggunakan nama apapun untuk even nya, pada contoh berikut ini kita akan menggunakan nama even 'message'createEventDispatcher harus dijalankan ketika komponen pertama dibentuk --- kita tidak bisa melakukan belakangan, contoh di dalam callback  setTimeout.  createEventDispatcher akan menyambungkan dispatch ke komponen yang terbentuk.

<script>
 // Inner.svelte

import { createEventDispatcher } from 'svelte';

const dispatch = createEventDispatcher();

function sayHello() {
dispatch('message', {
text: 'Hello!'
});
}
</script>

Sesudah itu kita bisa menggunakan komponen di app utama. Kita bisa melakukan alert teks yang kita dapatkan dari komponen, yang tersimpan dalam event.detail. Perhatikan nama even yang kita pakai di komponen Inner adalah 'message', kita bisa menggunakan nama yang lain.

<script>
import Inner from './Inner.svelte';

function handleMessage(event) {
alert(event.detail.text); // Hello! from Inner.svelte
}
</script>

<Inner on:message={handleMessage}/>

Event Forwarding


Tidak seperti even DOM, even komponen tidak bersifat bubble. Jika kita ingin menangkap suatu even yang terjadi dalam komponen di dalam komponen dst, komponen lain yang menjadi komponen perantaranya harus mem forward even tersebut. Sebagai contoh jika kita mempunyai App.svelte untuk app utama, Inner.svelte dan Outer.svelte adalah komponen yang akan digunakan di app utama. Outer akan mengandung komponen Inner  (App <- Outer <- Inner). Ketika Inner dispatch even, even itu tidak bisa digunakan di app utama, kecuali kita melakukan forward even yang di komponen Outer. Di bawah ini adalah contoh forward even di Outer.svelte. Perhatikan bagian <Inner on:message/> dan BUKAN <Inner/>

<script>
import Inner from './Inner.svelte';
</script>

<Inner on:message/>

DOM Event Forwarding


Forward even juga bisa digunakan untuk even DOM juga. Sebagai contoh jika kita membuat button custom seperti berikut:

<style>
button {
height: 4rem;
width: 8rem;
background-color: #aaa;
border-color: #f1c40f;
color: #f1c40f;
font-size: 1.25rem;
background-image: linear-gradient(45deg, #f1c40f 50%, transparent 50%);
background-position: 100%;
background-size: 400%;
transition: background 300ms ease-in-out;
}
button:hover {
background-position: 0;
color: #aaa;
}
</style>

<button>Click me</button>

Kemudian kita gunakan button itu di app utama:

<script>
import CustomButton from './CustomButton.svelte';

function handleClick() {
alert('clicked');
}
</script>

<CustomButton on:click={handleClick}/>

Program ini tidak akan berjalan, seperti yang kita lihat di CustomButton.svelte kita belum menambahkan even forwarding, jadi daripada menggunakan  <button>Click me</button>, kita harus menggunakan <button on:click>Click me</button> untuk menjalankan event forwarding.


Svelte Tutorial 4: Logic (Branch, Loop, and Async) (English & Indonesia)

English


Svelte offer ways to express logic, which HTML doesn't. Rule of the thumb is
{# to start logic block (ifeachawait)
{: for continuation logic block (elsethencatch)
{/ to close logic block

If Blocks (decision/branch)


We use tag {#if condition}{/if}  to do logical if. Here is some code example:

<script>
let user = { loggedIn: false }; function toggle() {
user.loggedIn = !user.loggedIn;
}
</script>

{#if user.loggedIn}
<button on:click={toggle}>
Log out
</button>
{/if}

{#if !user.loggedIn}
<button on:click={toggle}>
Log in
</button>
{/if}

Else


Use {:else} to do logical else. If else block will look like this

{#if [condition]}
  ...
{:else}
  ...
{/if}

# character always indicates a block opening tag. A / character always indicates a block closing tag. A : character, as in {:else}, indicates a block continuation tag.

Else if


You can chain multiple condition using else if like this:

{#if [condition]}
  ...
{:else if [condition]}
  ...
{:else}
  ...
{/if}

Each  (looping)


If you need to loop over lists of data, use an each block:

<script>
let cats = [
{ id: 'J---aiyznGQ', name: 'Keyboard Cat' },
{ id: 'z_AbfPXTKms', name: 'Maru' },
{ id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' }
];
</script>

<h1>The Famous Cats of YouTube</h1>
<ul>
{#each cats as cat}
<li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
{cat.name}
</a></li>
{/each}
</ul>

You can get the current index as a second argument, like so:

{#each cats as cat, i}
<li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
{i + 1}: {cat.name}
</a></li>
{/each}

If you prefer, you can use destructuring — each cats as { id, name } — and replace cat.id and cat.name with id and name.

{#each cats as { id, name }, i}
<li><a target="_blank" href="https://www.youtube.com/watch?v={id}">
{i + 1}: {name}
</a></li>
{/each}

Keyed each


When you add or remove something from each block, it will remove or add at the last position of data. But sometimes it's not what we want, for example when you use array operation slice(1), you want to remove first data without re-rendering/reset the rest. So in order to match the perspective we use keyed each to mark each generated object as unique like this:

{#each things as thing (thing.id)}
<Thing current={thing.color}/>
{/each}

instead of:

{#each things as thing}
<Thing current={thing.color}/>
{/each}

so when we remove first position of array, the component that is removed in the each block is also the first one not the last one, for interactive example you can check this https://svelte.dev/tutorial/keyed-each-blocks

Await Block (async calls)


Most web applications have to deal with asynchronous data at some point. Svelte makes it easy to await the value of  directly in your markup. Here is the example of await block:

{#await promise}
<p>...waiting</p>
{:then number}
<p>The number is {number}</p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await}

For example:

<script>
  let promise = exampleAsync();
  async function exampleAsnyc() {
    await new Promise(r => setTimeout(r, 2000)); // eg. hitting certain API
    return Math.random()

  }
  function onClick() { promise = exampleAsync(); }
</script>
<button on:click="onClick">Click Me!</button>





Indonesia


Svelte memberikan jalan untuk melakukan operasi-operasi logika, yang tidak ada di dalam HTML. Aturan sintaks yang perlu dipegang adalah sebagai berikut:
{# untuk memulai blok logika (ifeachawait)
{: untuk melakukan sambungan dengan blok logika di atasnya (elsethencatch)
{/ untuk menutup blok logika

If Blocks (decision/branch)


Kita menggunakan {#if condition}{/if}  untuk melakukan logika if. Di bawah ini adalah contohnya:

<script>
let user = { loggedIn: false };  function toggle() {
user.loggedIn = !user.loggedIn;
}
</script>

{#if user.loggedIn}
<button on:click={toggle}>
Log out
</button>
{/if}

{#if !user.loggedIn}
<button on:click={toggle}>
Log in
</button>
{/if}

Else


Gunakan {:else} untuk melakukan logika else. Blok else bisa dilakukan seperti ini:
{#if [condition]}
  ...
{:else}
  ...
{/if}

Karakter # akan mengindikasikan tag pembukaan blok. Karakter / akan selalu mengindikasikan tag penutupan. Karakter : seperti di {:else}, mengindikasikan tag sambungan blok.

Else if


Kita bisa melakukan kondisi berantai dengan else if seperti ini:

{#if [condition]}
  ...
{:else if [condition]}
  ...
{:else}
  ...
{/if}

Each  (looping)


Jika ingin melakukan loop pada sekumpulan data, gunakan each:

<script>
let cats = [
{ id: 'J---aiyznGQ', name: 'Keyboard Cat' },
{ id: 'z_AbfPXTKms', name: 'Maru' },
{ id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' }
];
</script>

<h1>The Famous Cats of YouTube</h1>
<ul>
{#each cats as cat}
<li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
{cat.name}
</a></li>
{/each}
</ul>

Kita bisa mendapatkan indeks data sebagai argumen kedua, seperti ini

{#each cats as cat, i}
<li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
{i + 1}: {cat.name}
</a></li>
{/each}

Bisa juga menggunakan destructuring— each cats as { id, name } — untuk menggantikan cat.id dan cat.name dengan id dan name.

{#each cats as { id, name }, i}
<li><a target="_blank" href="https://www.youtube.com/watch?v={id}">
{i + 1}: {name}
</a></li>
{/each}

Keyed each


Ketika kita menambahkan atau menghapus komponen dari blok each, maka yang akan dirubah adalah komponen pada posisi paling akhir/bawah. Tapi kadang itu tidak sesuai dengan apa yang kita mau, contohnya jika kita menggunakan operasi array slice(1), kita ingin menghilangkan data yang paling atas/pertama, tanpa perlu mengatur ulang data yang tersisa. Maka untuk menyamakan perspektif kita bisa menggunakan keyed each untuk menandai masing-masing komponen yang ada.

{#each things as thing (thing.id)}
<Thing current={thing.color}/>
{/each}

dan bukan seperti ini:

{#each things as thing}
<Thing current={thing.color}/>
{/each}

jadi ketika kita menghapus array posisi pertama, maka komponen yang akan dihilangkan juga yang pertama bukan yang terakhir, untuk contoh interaktif bisa dilihat di https://svelte.dev/tutorial/keyed-each-blocks.

Await Block (async calls)


Kebanyakan aplikasi web harus berurusan dengan  asynchronous data pada suatu titik. Svelte membuat urusan ini menjadi mudah untuk menunggu data secara langsung pada markup HTML kita. Di bawah ini adalah contoh dari blok await:

{#await promise}
<p>...waiting</p>
{:then number}
<p>The number is {number}</p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await}

Begini contoh cara pakainya:

<script>
  let promise = exampleAsync();
  async function exampleAsnyc() {
    await new Promise(r => setTimeout(r, 2000)); // eg. hitting certain API
    return Math.random()

  }
  function onClick() { promise = exampleAsync(); }
</script>

<button on:click="onClick">Click Me!</button>

2020-04-21

Svelte Tutorial 3: Component Properties (English & Indonesia)

English


Props or properties used when we want to pass data or value from one component to its children.

Declaring props


To declare props we need to use keyword export. For example when we have app like this:

<script>
import Nested from './Nested.svelte';
</script>

<Nested answer={42}/>  <!-- undefined if we forget keyword 
                            'export' when declaring answer -->

We need to declare answer with export keyword in Nested.svelte, otherwise answer will be considered undefined in the app

<script>
export let answer;
</script>

<p>The answer is {answer}</p>

Default value


We can also specify default value of answer from previous example like this:

<script>
export let answer = 'default';
</script>

So if we have something like this:

<Nested answer={42}/>  <!-- will print 42 -->
<Nested/>              <!-- will print default -->

Spread props


Assuming you have Info.svelte component which have 4 props (nameversionspeedwebsite),

<script>
export let name;
export let version;
export let speed;
export let website;
</script>
<p>
The <code>{name}</code> package is {speed} fast.
Download version {version} from <a href="https://www.npmjs.com/package/{name}">npm</a>
and <a href={website}>learn more here</a>
</p>

you can assign value like this:

<script>
import Info from './Info.svelte';

const pkg = {
name: 'svelte',
version: 3,
speed: 'blazing',
website: 'https://svelte.dev'
};
</script>

<Info name={pkg.name} version={pkg.version} speed={pkg.speed} website={pkg.website}/>

But instead of specifying one by one, you can also spread value like this, note that index name must be the same with the component.

<Info {...pkg}/>





Indonesia


Property adalah sesuatu yang digunakan untuk memberikan data atau nilai dari suatu komponen ke level komponen di bawahnya (child).

Declaring props


Untuk mendeklarasikan property kita bisa menggunakan keyword export. Sebagai contoh jika kita mempunyai app seperti ini:

<script>
import Nested from './Nested.svelte';
</script>

<Nested answer={42}/>  <!-- undefined jika kita lupa keyword 
                            'export' saat deklarasi answer -->

Kita harus mendeklarasikan answer dengan keyword export di dalam Nested.svelte, jika tidak maka answer tidak akan dikenali di app utama.

<script>
export let answer;
</script>

<p>The answer is {answer}</p>

Default value


Kita juga bisa memberikan nilai default pada variable answer dari contoh sebelumnya:

<script>
export let answer = 'default';
</script>

Jadi jika kita memanggil nested seperti ini:

<Nested answer={42}/>  <!-- akan mencetak 42 -->
<Nested/>              <!-- akan mencetak 'default' --> 


Spread props


Misalkan kita mempunyai komponen Info.svelte yang memiliki 4 properti (nameversionspeedwebsite)

<script>
export let name;
export let version;
export let speed;
export let website;
</script>
<p>
The <code>{name}</code> package is {speed} fast.
Download version {version} from <a href="https://www.npmjs.com/package/{name}">npm</a>
and <a href={website}>learn more here</a>
</p>

kita bisa memasukkan nilai variabel seperti ini:

<script>
import Info from './Info.svelte';

const pkg = {
name: 'svelte',
version: 3,
speed: 'blazing',
website: 'https://svelte.dev'
};
</script>

<Info name={pkg.name} version={pkg.version} speed={pkg.speed} website={pkg.website}/>

Akan tetapi daripada memasukan satu-satu, kita juga bisa langsung memasukkan variabel seperti contoh di bawah ini. Tapi satu hal yang perlu diperhatikan nama indeks pkg yang digunakan harus sama dengan di Info.svelte yaitu (nameversionspeedwebsite)

<Info {...pkg}/>


2020-04-10

Svelte Tutorial 2: Reactivity (English & Indonesia)

English


Reactivity is the ability of the system in svelte to keep DOM in sync with application state. Svelte automatically update DOM/invalidate state if there's an assignment operator. Below is explanation of reactivity in Svelte:

Assignment


For example when you have function handleClick like this:

<script>
 let count = 0;

 function handleClick() {
  count += 1;
 }
</script>

<button on:click={handleClick}>
   Clicked {count} {count === 1 ? 'time' : 'times'}
</button>


that is called everytime there is a click on the button, when handleClick assign new value to variable count the text on the button get updated automatically, so it will represent new value of count.

Declaration


When you want to have variable that respond to change of state happen within your app, use reactive declaration like this:

<script>
 let count = 0;
 $: doubled = count * 2;      // reactive declaration
 function handleClick() {

  count += 1;
 }

</script>

<button on:click={handleClick}>
 Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

<p>{count} doubled is {doubled}</p>


Notice the $: sign before declaring doubled, so when count variable gets updated doubled also changed to represent new value.

Statement


You can also use reactive declaration for any statement, for example, we can log the value of count whenever it changes:

$: console.log(`the count is ${count}`);

you can also grouped several statement together:

$: {
 console.log(`the count is ${count}`);
 alert(`I SAID THE COUNT IS ${count}`);
}


you can even use reactivity for if statement:

<script>
 let count = 0;
 $: if (count >= 10) {
  alert(`count is dangerously high!`);
  count = 9;
 }
 function handleClick() {
  count += 1;
 }
</script>
<button on:click={handleClick}>
 Clicked {count} {count === 1 ? 'time' : 'times'}
</button>


Notice the $: sign before every statement or block of statement, if you are not using this, then your statement wont be reactive and wont be executed as the value of variable changed.

Updating array or object


Because in svelte reactivity is triggered by assignment, if you use array method like push, new state wont be updated. So you will have to add another line that seem redundant but since it does assignment, it will trigger reactivity

numbers.push(numbers.length + 1);  // no assignment = not reactive
numbers = numbers                  // has assignment = reactive


you can also use something like this  (will be reactive)

numbers = [...numbers, numbers.length + 1];

Assignments to properties of arrays and objects — e.g.
obj.foo += 1 or array[i] = x , work the same way as assignments to the values themselves (will be reactive). A simple rule of thumb: the name of the updated variable must appear on the left hand side of the assignment. This example below won't update references to obj.foo.bar, unless you follow it up with obj = obj.

const foo = obj.foo;
foo.bar = 'baz';







Indonesia


Reactivity adalah kemampuan sistem svelte untuk mejaga DOM tetap sama dengan keadaan aplikasi. Svelte akan meng update DOM/invalidate state secara otomatis apabila ada operasi perubahan/pengisian nilai ke dalam variabel menggunakan operator assignment (=). Berikut di bawah ini adalah penjelasan reactivity dalam svelte:

Assignment


Sebagai contoh ketika kita mempunyai fungsi handleClick seperti ini:

<script>
 let count = 0;

 function handleClick() {
  count += 1;
 }
</script>

<button on:click={handleClick}>
   Clicked {count} {count === 1 ? 'time' : 'times'}
</button>


yang akan dipanggil setiap kali ada klik pada button, maka ketika handleClick mengisi  nilai yang baru ke variable count, tulisan pada tombol akan terupdate secara otomatis, menyesuaikan dengan nilai yang baru count.

Declaration


Ketika kita ingin mempunya variabel yang merespon perubahan nilai yang terjadi di aplikasi, gunakan deklarasi reactive seperti ini:

<script>
 let count = 0;
 $: doubled = count * 2;      // deklarasi reactive
 function handleClick() {

  count += 1;
 }

</script>

<button on:click={handleClick}>
 Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

<p>{count} doubled is {doubled}</p>


Perhatikan tanda $: sebelum deklarasi variabel doubled, maka ketika variabel count dirubah nilainya, variabel doubled juga akan berubah menyesuaikan dengan nilai baru yang semestinya.

Statement


Kita juga bisa menggunakan deklarasi reactive untuk kalimat apapun, sebagai contoh, kita bisa memasukkan perubahan nilai count ke dalam log:

$: console.log(`the count is ${count}`);

bisa juga mengelompokkan beberapa baris:

$: {
 console.log(`the count is ${count}`);
 alert(`I SAID THE COUNT IS ${count}`);
}


bahkan bisa digunakan untuk kalimat if

<script>
 let count = 0;
 $: if (count >= 10) {
  alert(`count is dangerously high!`);
  count = 9;
 }
 function handleClick() {
  count += 1;
 }
</script>
<button on:click={handleClick}>
 Clicked {count} {count === 1 ? 'time' : 'times'}
</button>


Perhatikan tanda $: sebelum semua kalimat atau kelompok kalimat, jika lupa menambahkan tanda ini maka kalimat itu tidak akan reactive dan tidak akan dieksekusi biarpun ada perubahan nilai pada variabel.

Updating array or object


Karena di svelte reactivity dipicu oleh assignment (tanda =) , jika kita menggunakan method array seperti push, maka reactivity tidak akan berjalan. Maka untuk memancing supaya reactive, kita bisa menambahkan baris (yang terlihat redundant) seperti di bawah ini:

numbers.push(numbers.length + 1);  // no assignment = not reactive
numbers = numbers                  // has assignment = reactive


Kita juga bisa menggunakan penambahan array seperti di bawah ini (akan reactive):

numbers = [...numbers, numbers.length + 1];

Assignment pada properti objek atau array — seperti ini:
obj.foo += 1 atau array[i] = x , akan menghasilkan sesuatu yang sama dengan jika melakukan assignment pada nilai variabel langsung (jadi akan reactive). Aturan sederhana yang bisa kita pegang adalah jika nama dari variabel yang diubah nilai nya ada di sebelah kiri operator assignment (tanda =) maka akan memicu reactivity.
Contoh di bawah ini tidak akan mengubah nilai pada obj.foo.bar, karena obj.foo ada di sebelah kanan, kecuali kita menambahkan obj = obj untuk memancing reactivity

const foo = obj.foo;
foo.bar = 'baz';


Svelte Tutorial 1: Introduction to Svelte (English & Indonesia)

English


Svelte is a tool for building fast web applications. It's a competitor to React, Vue, Ember, Aurelia, and Angular, but it's better since it was compiled/errors checked at compile time before combined into a bundle.js file, not needing any virtual DOM/different template file/language like JSX, also because Svelte has the lowest learning curve among all. To learn more why Svelte is better than the rest, see Rich Harris' presentation about Rethinking Reactivity. To create a new svelte project use this command after you installed nodejs, npm, and npx:

npx degit sveltejs/template project1
cd project1
npm install # install dependencies
npm run dev


You can look at the result in the browser, and edit that project directly side by side (it has live reload). In Svelte, an application is composed from one or more components. A component is a reusable self-contained block of code that encapsulates HTML, CSS and JavaScript that belong together, written into a .svelte file. Here are some basics in svelte:

How to declare and use variable


First, add a <script> tag to your component and declare a variable (name)

<script>
let name = 'world';
</script>

Then, we can refer to variable in the markup using curly braces.

<h1>Hello {name}!</h1>

We can also use curly braces to put any JS we want.

How to create dynamic attributes:


We can use variable to create dynamic attributes:

<script>
let src = 'tutorial/image.gif';
</script>
<img src={src}>

We can use variable to specify image source, so we can dynamically determine link source programmatically for example.

You can also use shorthand feature when variable name and attribute is the same, like this:

<img {src}>

Styling


Just like in HTML, you can add a <style> tag to your component:

<style>
p {
color: purple;
font-family: 'Comic Sans MS', cursive;
font-size: 2em;
}
</style>


<p>This is a paragraph.</p>

What is special in svelte is style is scoped within component so when you set <p> style in one component, it wont accidentally change <p> style elsewhere within your app.

Nested component


It would be impractical to put your entire app in a single component. Instead, we can import components from other files and include them as though we were including elements.

For example we can have file Nested.svelte like this:

<p>This is another paragraph.</p>

Then we can use Nested component by importing it like this:

<script>
import Nested from './Nested.svelte';
</script>

Nested in this case can be anything, and totally independent to the file name (So you can name it anything, but it's a good practice to import with same name as the file name). And when we want to use it, just use it like you would when using predefined tags

<p>This is a paragraph.</p> <!-- normal predefined tag -->

<Nested/>                   <!-- your made up tag -->

Notice that even though both  <p> and <Nested> actually used same  <p> tag, but each style is independent as now its considered different component. One more thing to remember, tag name is case sensitive, so <Nested> not the same with <nested>

Unescaping HTML tags


Ordinarily, strings are inserted as plain text, meaning that characters like < and > have no special meaning. But sometimes you need to render HTML directly into a component. For example, the words you're reading right now exist in a markdown file that gets included on this page as a blob of HTML.

<script>
let str = `string contains <strong>HTML!!!</strong>`;
</script>

So instead of doing this:

<p>{str}</p>

In Svelte, you can do this with the special {@html ...} tag:

<p>{@html str}</p>



Indonesia


Svelte adalah alat untuk membuat web application secara cepat. Svelte adalah pesaing dari ReactVueEmberAurelia, and Angular, tapi svelte kami nilai lebih baik karena dicompile dan dicek error nya saat compile, baru kemudian digabungkan dalam file bundle.js, dan tidak membutuhkan virtual DOM atau file/bahasa template yang berbeda seperti JSX, svelte juga termasuk yang paling mudah dipelajari dibanding yang lainnya. Untuk lebih meyakinkan kenapa Svelte lebih baik dari yang lain, kamu bisa tonton persentasi Rich Harris tentang Rethinking Reactivity. Untuk membuat project Svelte yang baru gunakan perintah ini sesudah kamu menginstall nodejs, npm, dan npx:

npx degit sveltejs/template project1
cd project1
npm install # install dependencies
npm run dev


Kamu bisa melihat hasil web mu di browser, dan meng edit project itu langsung secara berdampingan (Svelte punya live reload). Di dalam svelte aplikasi dibentuk dari satu atau lebih komponen. sebuah komponen adalah blok program yang berdiri sendiri dan bisa digunakan berulang kali, yang terdiri atas HTML, CSS dan Javascript yang saling berhubungan, dikumpulkan menjadi satu dalam file .svelte. Berikut adalah dasar-dasar dalam Svelte:

Cara mendeklarasi dan menggunakan variabel

Pertama, tambahkan tag <script> dan deklarasikan variabel (name)

<script>
let name = 'world';
</script>

Kemudian kita bisa menggunakan variabel di dalam markup menggunakan kurung kurawal.

<h1>Hello {name}!</h1>

Kita juga bisa menggunakan kurung kurawal untuk memasukkan program JS.

Cara membuat atribut yang dinamis


Kita bisa menggunakan variabel untuk membuat atribut yang dinamis:

<script>
let src = 'tutorial/image.gif';
</script>
<img src={src}>

Karena kita bisa menggunakan variabel untuk memasukkan alamat asal image, maka kita bisa mengatur alamatnya secara dinamis dalam pemrograman.

Kita juga bisa menggunakan cara singkat jika nama variabel dan nama atributnya sama, seperti ini:

<img {src}>

Styling


Sama persis seperti di HTML, kamu juga bisa menambahkan tag  <style> ke komponen yang kamu buat.

<style>
p {
color: purple;
font-family: 'Comic Sans MS', cursive;
font-size: 2em;
}
</style>

<p>This is a paragraph.</p>

Yang istimewa dari svelte adalah style yang kamu tambahkan akan dibatasi hanya di dalam komponen tersebut, jadi misal dalam contoh di atas, style warna ungu tidak akan merubah style <p> lainnya dalam aplikasi buatanmu.

Nested component


Untuk tujuan pembuatan aplikasi yang baik, alangkah baiknya apabila kita tidak memasukkan smua app kita dalam satu komponen saja, melainkan bisa dipecah-pecah menjadi beberapa komponen kecil yang bisa digunakan berulang kali apabila dibutuhkan di kemudian hari. Kita bisa import komponen yang sudah dibuat tadi dari file lain dan di include kan seperti jika kita meng include kan elemen.

Sebagai contoh jika kita mempunya file Nested.svelte yang isinya seperti ini:

<p>This is another paragraph.</p>

Maka kita bisa memasukkan komponen Nested dengan cara import seperti ini:

<script>
import Nested from './Nested.svelte';
</script>

Nama elemen Nested bisa saja dirubah dengan nama lain, jadi nama ini tidak berhubungan dengan nama file nya (tapi akan jadi kebiasaan yang lebih baik jika dinamakan sama saja dengan nama file nya, supaya tidak bingung sendiri begitu maksudnya). Kemudian jika mau menggunakan tinggal gunakan dengan cara yang sama seperti menggunakan tag HTML pada umumnya.

<p>This is a paragraph.</p> <!-- html normal -->

<Nested/>                   <!-- tag buatan sendiri -->

Perhatikan meskipun kedua <p> dan <Nested> sebenarnya sama2 menggunakan tag <p>, tapi style masing2 tidak akan saling mempengaruhi, karena sekarang mereka sudah dianggap sebagai komponen yang berbeda. Satu lagi yang harus diingat, nama komponen buatanmu sifatnya case sensitive, jadi <Nested>  tidak sama dengan <nested>

Unescaping tag HTML


Biasanya, string akan dianggap sebagai plain text, jadi jika di dalam string itu ada karakter seperti   < dan > maka tidak akan dianggap sebagai sesuatu yang istimewa. Tapi kadang kita memang ingin menganggapnya sebagai HTML dan memasukkan langsung ke dalam komponen. Sebagai contoh kata-kata yang dimasukkan mengandung tag <strong>, supaya tulisan jadi bold.

<script>
let str = `string contains <strong>HTML!!!</strong>`;
</script>

Maka daripada memasukkan variabel seperti biasa dengan kurung kurawal:

<p>{str}</p>

Di svelte kita bisa melakukan dengan tag {@html ...} seperti ini, maka tulisan akan mengandung bold di bagian yang ada tag <strong>:

<p>{@html str}</p>