Switching between Login Form and Register Form in VueJS template

Recently, I attempted to switch between the 'Login Form' and 'Register Form' using code that I found on codepen Flat HTML5/CSS3 Login Form. While the code functioned properly on its own, when integrated into a Vue Template, the form failed to transition to the 'Create an account' form. It seems there might be an issue with the JavaScript that needs correction.

The code I used is displayed below:

HTML

<template id="login-page"> // ISSUE When this Tag is incorporated and called through VueJS component
<div class="login-page">
  <div class="form">
    <form class="register-form">
      <input type="text" placeholder="name"/>
      <input type="password" placeholder="password"/>
      <input type="text" placeholder="email address"/>
      <button>create</button>
      <p class="message">Already registered? <a href="#">Sign In</a></p>
    </form>
    <form class="login-form">
      <input type="text" placeholder="username"/>
      <input type="password" placeholder="password"/>
      <button>login</button>
      <p class="message">Not registered? <a href="#">Create an account</a></p>
    </form>
  </div>
</div>
</template>  // ISSUE When this Tag is incorporated and called through VueJS component

VueJS

// Vue component: login-page
const LoginPage = {
    template: '#login-page',
    data() {
        return {
            login_message: 'Please enter your credentials to login.',
            loginStage: 'login-form',
            }
        },
    }

JavaScript

<script>
$('.message a').click(function(){
   $('form').animate({height: "toggle", opacity: "toggle"}, "slow");
});
</script>

CSS

<style>
@import url(https://fonts.googleapis.com/css?family=Roboto:300);

.login-page {
  width: 360px;
  padding: 8% 0 0;
  margin: auto;
}
.form {
  position: relative;
  z-index: 1;
  background: #FFFFFF;
  max-width: 360px;
  margin: 0 auto 100px;
  padding: 45px;
  text-align: center;
  box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
}
.form input {
  font-family: "Roboto", sans-serif;
  outline: 0;
  background: #f2f2f2;
  width: 100%;
  border: 0;
  margin: 0 0 15px;
  padding: 15px;
  box-sizing: border-box;
  font-size: 14px;
}
.form button {
  font-family: "Roboto", sans-serif;
  text-transform: uppercase;
  outline: 0;
  background: #4CAF50;
  width: 100%;
  border: 0;
  padding: 15px;
  color: #FFFFFF;
  font-size: 14px;
  -webkit-transition: all 0.3 ease;
  transition: all 0.3 ease;
  cursor: pointer;
}
.form button:hover,.form button:active,.form button:focus {
  background: #43A047;
}
.form .message {
  margin: 15px 0 0;
  color: #b3b3b3;
  font-size: 12px;
}
.form .message a {
  color: #4CAF50;
  text-decoration: none;
}
.form .register-form {
  display: none;
}
.container {
  position: relative;
  z-index: 1;
  max-width: 300px;
  margin: 0 auto;
}
.container:before, .container:after {
  content: "";
  display: block;
  clear: both;
}
.container .info {
  margin: 50px auto;
  text-align: center;
}
.container .info h1 {
  margin: 0 0 15px;
  padding: 0;
  font-size: 36px;
  font-weight: 300;
  color: #1a1a1a;
}
.container .info span {
  color: #4d4d4d;
  font-size: 12px;
}
.container .info span a {
  color: #000000;
  text-decoration: none;
}
.container .info span .fa {
  color: #EF3B3A;
}
body {
  background: #76b852; /* fallback for old browsers */
  background: -webkit-linear-gradient(right, #76b852, #8DC26F);
  background: -moz-linear-gradient(right, #76b852, #8DC26F);
  background: -o-linear-gradient(right, #76b852, #8DC26F);
  background: linear-gradient(to left, #76b852, #8DC26F);
  font-family: "Roboto", sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;      
}
</style>

Answer №1

Although @Fred has acknowledged @chr's response, the use of Vue in this context is not ideal.
(It is important to note that this is not an attempt to recreate a functional fiddle, but rather to address the broader query of how to Switch between 'Login Form' & 'Register Form' utilizing a more Vue-centric approach)

In Vue, transitioning between the login form and register form should be achieved through markup using Vue conditional rendering instead of invoking functions like showRegisterForm() and showLoginForm().
The toggleForm method does not need any parameters because the model already knows the value of currentForm.

The simplest way to accomplish this is with an if statement paired with an else, leveraging a property in your Vue model such as currentForm: 'login' introduced in @chr's answer.
Only minor adjustments are required in the HTML

<div id="login-page" class="login-page">
  <div class="form">
    <form v-if="currentForm.toLowerCase() === 'register'" class="register-form">
      <input type="text" placeholder="name"/>
      <input type="password" placeholder="password"/>
      <input type="text" placeholder="email address"/>
      <button>create</button>
      <p class="message">Already registered?
          <a href="#" @click.prevent="toggleForm()">Sign In</a></p>
    </form>
    <form v-else class="login-form">
      <input type="text" placeholder="username"/>
      <input type="password" placeholder="password"/>
      <button>login</button>
      <p class="message">Not registered?
          <a href="#" @click.prevent="toggleForm()">Create an account</a></p>
    </form>
  </div>
</div>

A snippet of the model necessary for this operation could look like

const model = new Vue({
    data : {
        'currentForm' : 'login',
        ...
    },
    ...
    methods : {
        toggleForm() {
            this.currentForm = this.currentForm === 'login' ? 'register' : 'login';
        }
    },
    ...
});

When currentForm changes, Vue will automatically handle which form is displayed.

For a more generalized approach, refer to the response to the question VueJS - Swap component on click.

Answer №2

You may be confusing the roles of Vue as a library versus Vue as a framework. It seems like you are trying to utilize Vue as a library, so I have made adjustments to the code accordingly. Here is my updated JSFiddle for reference. To implement transitions, refer to the documentation on Enter/Leave & List Transitions.

HTML:

<div id="login-page" class="login-page">
  <div class="form">
    <form class="register-form" v-show="showRegisterForm">
      <input type="text" placeholder="name"/>
      <input type="password" placeholder="password"/>
      <input type="text" placeholder="email address"/>
      <button>create</button>
      <p class="message">Already registered? <a href="#" @click.prevent="toggleForm('login')">Sign In</a></p>
    </form>
    <form class="login-form" v-show="showLoginForm">
      <input type="text" placeholder="username"/>
      <input type="password" placeholder="password"/>
      <button>login</button>
      <p class="message">Not registered? <a href="#" @click.prevent="toggleForm('register')">Create an account</a></p>
    </form>
  </div>
</div>

JS:

new Vue({
  el: '#login-page',
  data() {
      return {
        login_message: 'Please enter your credentials to login.',
        loginStage: 'login-form',
        currentForm: 'login',
      }
    },
  computed: {
        showRegisterForm() {
        return this.currentForm === 'register';
    },
    showLoginForm() {
        return this.currentForm === 'login';
    },
  },
    methods: {
        toggleForm(formName) {
        this.currentForm = formName;
    },
  },
});

CSS:

@import url(https://fonts.googleapis.com/css?family=Roboto:300);

.login-page {
  width: 360px;
  padding: 8% 0 0;
  margin: auto;
}
.form {
  position: relative;
  z-index: 1;
  background: #FFFFFF;
  max-width: 360px;
  margin: 0 auto 100px;
  padding: 45px;
  text-align: center;
  box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
}
.form input {
  font-family: "Roboto", sans-serif;
  outline: 0;
  background: #f2f2f2;
  width: 100%;
  border: 0;
  margin: 0 0 15px;
  padding: 15px;
  box-sizing: border-box;
  font-size: 14px;
}
.form button {
  font-family: "Roboto", sans-serif;
  text-transform: uppercase;
  outline: 0;
  background: #4CAF50;
  width: 100%;
  border: 0;
  padding: 15px;
  color: #FFFFFF;
  font-size: 14px;
  -webkit-transition: all 0.3 ease;
  transition: all 0.3 ease;
  cursor: pointer;
}
.form button:hover,.form button:active,.form button:focus {
  background: #43A047;
}
.form .message {
  margin: 15px 0 0;
  color: #b3b3b3;
  font-size: 12px;
}
.form .message a {
  color: #4CAF50;
  text-decoration: none;
}

.container {
  position: relative;
  z-index: 1;
  max-width: 300px;
  margin: 0 auto;
}
.container:before, .container:after {
  content: "";
  display: block;
  clear: both;
}
.container .info {
  margin: 50px auto;
  text-align: center;
}
.container .info h1 {
  margin: 0 0 15px;
  padding: 0;
  font-size: 36px;
  font-weight: 300;
  color: #1a1a1a;
}
.container .info span {
  color: #4d4d4d;
  font-size: 12px;
}
.container .info span a {
  color: #000000;
  text-decoration: none;
}
.container .info span .fa {
  color: #EF3B3A;
}
body {
  background: #76b852; /* fallback for old browsers */
  background: -webkit-linear-gradient(right, #76b852, #8DC26F);
  background: -moz-linear-gradient(right, #76b852, #8DC26F);
  background: -o-linear-gradient(right, #76b852, #8DC26F);
  background: linear-gradient(to left, #76b852, #8DC26F);
  font-family: "Roboto", sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;      
}

Answer №3

@chr's solution worked for me, although I had to make some adjustments to the first two lines of the JavaScript code. In my situation, I already had a Vue instance that called the Login Component, which in turn activated the Login Template.

JavaScript

// Vue component: login-page
const LoginPage = {
    template: '#login-page',
    data() {
        return {
            login_message: 'Please enter your credentials to login.',
            currentForm: 'login',
            }
        },
    computed: {
        showRegisterForm() {
            return this.currentForm === 'register';
        },
        showLoginForm() {
            return this.currentForm === 'login';
            },
        },
    methods: {
        toggleForm(formName) {
        this.currentForm = formName;
        },
    },
}

Answer №4

Stephen P's solution is also effective and more organized, but it is worth noting that the first form should have the register in single quotes like 'register', which has been rectified below.

HTML Form:

<div id="login-page" class="login-page">
    <span><h1>{{currentForm.toUpperCase()}} FORM</h1></span>
    <span><h5>Please enter your credentials to {{currentForm.toLowerCase()}}.</h5></span>
    <div class="form">
        <form v-if="currentForm.toLowerCase() === 'register'" class="register-form">
        <input type="text" placeholder="name"/>
        <input type="password" placeholder="password"/>
        <input type="text" placeholder="email address"/>
        <button>create</button>
        <p class="message">Already registered? <a href="#" @click.prevent="toggleForm()">Sign In</a></p>
        </form>
        <form v-else class="login-form">
        <input type="text" placeholder="username"/>
        <input type="password" placeholder="password"/>
        <button>login</button>
        <p class="message">Not registered? <a href="#" @click.prevent="toggleForm()">Create an account</a></p>
        </form>
    </div>
</div>

JavaScript Logic:

// Vue component: login-page
const LoginPage = {
    template: '#login-page',
    data() {
        return {
            currentForm: 'login'
            }
        },
    methods: {
        toggleForm()
        {
            this.currentForm = this.currentForm === 'login' ? 'register' : 'login';
        }
    },
}

CSS Styling:

@import url(https://fonts.googleapis.com/css?family=Roboto:300);

.login-page {
  width: 360px;
  padding: 8% 0 0;
  margin: auto;
}
/* Additional CSS styles go here */

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ways to streamline the directives for conciseness?

This section contains a login field where users can input their username, password, and click the login button. It may seem lengthy and detailed at first glance. <form name='form' novalidate ng-submit="form.$valid && submit('/log ...

Create a customized HTML popup featuring various packages

I am struggling to create an HTML popup within a React component due to some errors Here is the code snippet: <div> <button class="toggle">Button</button> <div id="link-box"> <ul> ...

Ways to Retrieve HTML Snippet from Handler Request and Load it into a String

I'm encountering an issue with my ASP.NET MVC application. I'm attempting to retrieve the following HTML snippet from a Handler in a separate ASP.NET project, within one of my controllers, in order to display it in a View: <br /> <div i ...

How do I create a new JSON Object with only two properties by selecting from an existing JSON Object with four properties?

Below is a JSON object example: [ {'car':'punto','brand':'fiat','color':'black','model':'2007'}, {'car':'XUV500','brand':&ap ...

What is the best way to apply a texture to a triangle using three.js?

I've been able to add textures to cubes, spheres, and other primitives in a scene I created. However, when it comes to adding a texture to a simple triangle, I'm encountering difficulties. Below is my attempt at achieving this: var texture=TH ...

What could be causing the 500 internal server error when using jquery ajax with Python Bottle?

I am encountering a server 500 error while attempting an AJAX post. The python code appears to be error-free, so the issue likely lies within the callback function. Below is the current code I am using. Any suggestions? The HTML form portion represents th ...

The clickable area for the radio button cursor is too large

As I embark on my journey with HTML and CSS, I have encountered two issues while creating a form: The spacing between the question and answers is too wide. The second picture depicts how I would like it to appear. The cursor:pointer seems to be extending ...

Using Android to Load HTML Content from a Database and Display in a WebView

I am currently facing an issue with loading HTML content from my sqlite database into a webview successfully. The HTML renders beautifully, however, the local file included in the HTML is not being loaded. I have placed it in the assets folder under this s ...

Enhance your website with Jquery-powered page transitions that can easily be linked for a

I have a client who has a specific vision for their website. To demonstrate the concept, I've created a demo which can be viewed here: She requested page transitions similar to those in the demo for the main content. I used jQuery to implement this ...

Fetching Data Tables via Ajax Request

I'm attempting to retrieve data from a database using Jquery DataTable, but I keep encountering this error message: "DataTables warning: table id=tblBindData - Cannot reinitialise DataTable." function BindData() { $("#tblBindData").DataTab ...

Unable to send an API request from Postman to a database through express and mongoose technology

This is my server.js: const express= require('express'); const app = express(); // const mongoose= require('mongoose'); // load config from env file require("dotenv").config(); const PORT = process.env.PORT || 4000; // middl ...

Retrieve database SQL information using JavaScript to display data

I'm struggling to push the value from a textbox to SQL and display it. Despite reading numerous topics, I still can't figure it out. My explanation skills are lacking, but hopefully you can understand what I'm trying to achieve, especially i ...

Modify Knockout applyBindings to interpret select choices as numeric values

Utilizing Knockout alongside html select / option (check out Fiddle): <select data-bind="value: Width"> <option>10</option> <option>100</option> </select> Upon invoking applyBindings, the options are interprete ...

What is the best way to apply the :nth-child() selector to target every second <div> element within ALL child elements?

I'm currently developing a commenting feature, and I am in need of CSS to select every alternate child <div> (even children nested within the first set of children). Consider this example HTML structure: <body> <div class="comment"&g ...

PHP - WebCalendar - Show or Hide Field According to Selected Item in Dropdown List

Working with the WebCalendar app found at to make some personalized adjustments to how extra fields function. I've set up two additional fields: one is a dropdown list of counties, and the other is a text field. Within the dropdown list, there is an ...

When attempting to inject a provider from the same module, the dependencies cannot be resolved

Bug Report Current Issue Encountering an error when trying to instantiate the PaymentProcessorModule: Error: Nest cannot resolve dependencies of the PaymentProcessor (?, PaymentsService, ProcessingService). Please ensure that the TransactionsService argum ...

Can we limit the text in a specific cell to one line on a desktop for a responsive table?

I am facing a challenge with making the second cell in my table have a width of 100% while ensuring that the text stays on one line. While the mobile version is functioning correctly, I am struggling to find a solution for the desktop version as the last ...

The Right Way to Set Up Form Data in VueJS

Currently, I am facing an issue with a component that renders a form and pre-fills the fields with data retrieved from an ajax request. The problem lies in my desire to edit existing fields and simultaneously add new fields for submission. To accomplish t ...

Exploring the world of CouchDB through jQuery and AJAX POST requests while navigating

I am in the process of building a simple web application. Today, I installed Couch 1.3.1 and set up a database. I am currently trying to save a document to my local Couch (localhost:5984) using a POST request from a client browser that is also on localhost ...

Unable to establish a connection to the server while handling a jQuery Ajax error

I'm in the process of pinpointing an issue that occurs when submitting an Ajax request through jQuery and encountering a failed connection to the server. The scenario involves loading a page from the server, then deliberately disconnecting the network ...