isuckatcode
isuckatcode

Reputation: 88

Svelte's reactivity not working on class variables

So for form actions, I made a class to make things cleaner, but there's a problem. Whenever any errors/success messages are set in the class, Svelte does not automatically rerender the changes.

Frontend:

<script>

    import Form from '@/periphs/form'

    let changePasswordForm = new Form()

    changePasswordForm.form.values = {
        newPassword: null,
        currentPassword: null
    }

    changePasswordForm.params.endpoint = route('api.user.settings.security.change-password')

    const changePassword = () => {
        changePasswordForm.execute()
    }

</script>

<div class="block">

    <div class="is-size-6 has-text-weight-light">Change Password</div>

    <div class="field help has-text-grey-light">
        1. Use special characters. (!@#$%^&*)
        <br>2. Do not reuse passwords.
        <br>3. Do not use passwords that can be guessed. (Birthdays, names, numbers, etc).
    </div>
    
    <fieldset disabled={ changePasswordForm.form.processing }>

        <div class="field">

            <div class="control">
                <label for="" class="label is-small">New Password</label>
                <input bind:value={ changePasswordForm.form.values.newPassword } class:is-danger={ changePasswordForm.form.errors.newPassword } type="password" class="input is-small" placeholder="New Password">
            </div>

            {#if changePasswordForm.form.errors.newPassword}
                <div class="help is-danger">{ changePasswordForm.form.errors.newPassword }</div>
            {/if}

        </div>

        <div class="field">

            <div class="control">
                <label for="" class="label is-small">Current Password</label>
                <input bind:value={ changePasswordForm.form.values.currentPassword } class:is-danger={ changePasswordForm.form.errors.currentPassword } type="password" class="input is-small" placeholder="Current Password Password">
            </div>
            
            {#if changePasswordForm.form.errors.currentPassword}
                <div class="help is-danger">{ changePasswordForm.form.errors.currentPassword }</div>
            {/if}

        </div>

        <div class="field">

            <button on:click={ () => changePassword() } class="button is-primary is-small">Change Password</button>
            
            {#if changePasswordForm.form.success.message}
                <div class="help is-success">{ changePasswordForm.success.message }</div>
            {/if}

            {#if changePasswordForm.form.errors._flood}
                <div class="help is-danger">{ changePasswordForm.errors._flood }</div>
            {/if}

        </div>

    </fieldset>

</div>

Form.js:

'use strict'

import axios from "axios"

export default class Form {

    constructor() {
        this.form = {
            processing: false,
            success: {},
            errors:  {},
            values:  {}
        }
        this.params = {
            method:  'POST',
            endpoint: null,
        }
    }

    getErrors() {
        return this.form.errors
    }

    execute() {

        /*
            Before form submission, reset all errors/successes
        */

        this.form.processing = true
        this.form.success    = {}
        this.form.errors     = {}

        if (this.params.method == 'POST') {

            axios.post(this.params.endpoint).then(r => {
                
                /*
                    Handle success
                */

                this.form.errors = {}
                this.form.success = r.data

            }).catch(e => {

                /*
                    422
                    Form errors (Validation)
                */

                if (e.response.status == 422) {
                    this.form.errors = e.response.data.errors
                }

                /*
                    429
                    Request timeout (Flood)
                */

                if (e.response.status == 429) {
                    this.form.errors = { ...this.form.errors, ...{ '_flood': e.response.data.message } }
                }

                console.log(this.form.errors) // SHOWS ERRORS AS ITS SUPPOSED TO, BUT THIS IS NOT REPRODUCED ON THE FRONTEND

            }).finally(() => {
                this.form.processing = false
            })

        }

        
    }

}

Whenever there is an error/success, it should show those changes on my front end, but that is not the case. Any one got any idea on how to fix this?

Upvotes: 1

Views: 385

Answers (1)

brunnerh
brunnerh

Reputation: 185225

Reactivity only works for code within components, outside you need to use stores or events to signal changes.

Upvotes: 4

Related Questions