0

My "interact.html" just has Login form and two buttons, which called "Login" and "Register" respectively, if users want to create a new account, they need to click the button "Register", then the Login form will be changed to Register form by using Fetch API. If users want to change the Register form to the Login form again, they can click the button "Login", then the Login form will be changed to Register form by using Fetch API.

I write a file "accounts.js" to deal with the event on "interact.html"

First get the element:

get the "login-form"

const form = document.getElementById('login-form');

get login button

const log = document.getElementsByClassName('log-reg')[0];

get register button

const reg = document.getElementsByClassName('log-reg')[2];

Here is the the part of Fetch API

Change Register form to Login form

log.addEventListener('click', function(event){
    fetch('http://127.0.0.1:8090/interact?page=login')
     .then(response => response.text())
     .then(body =>
        form.innerHTML=body
    )
});

Change Login form to Register form

reg.addEventListener('click', function(event){
    fetch('http://127.0.0.1:8090/interact?page=register')
     .then(response => response.text())
     .then(body =>
        form.innerHTML=body
    )
});

Then Node.js(express) will return the html


app.get('/interact',(req,res) => {
    if(req.query.page==='register'){
        res.sendFile(path.join(__dirname+'/public/register-form.html'));
    }
    else if (req.query.page==='login'){
        res.sendFile(path.join(__dirname+'/public/login-form.html'));
    }
    else{
        res.sendFile(path.join(__dirname+'/public/interact.html'));
    }
})

This is "register-form.html"

<body>
    <div class="mb-3">
        <label for="setusername" class="form-label" style="font-size: 20px;">Set User name:</label>
        <br>
        <input class="form-control">
    </div>
    <br>
    <div class="mb-3">
        <label for="setpassword" class="form-label" style="font-size: 20px;">Set Password:</label>
        <br>
        <input type="password" class="form-control" id="setpassword">
    </div>

    <div class="mb-3">
        <label for="ensure" class="form-label" style="font-size: 20px;">Ensure Password:</label>
        <br>
        <input type="password" class="form-control" id="ensure">
    </div>
    <br>
    <button type="submit" class="btn btn-primary" id = "create">Register</button>
</body>

The "login-form.html" is similar to the "register-form.html"

After the Login form or Register form being changed, the element in "login-form.html" and "register-form.html" which is updated to "interact.html" by fetch() API can not be got.

can not get element "create"

const create = document.getElementById('create');

Because when I write

create.addEventListener('click',function(event){})

The browser will report Uncaught TypeError: Cannot read properties of null (reading 'addEventListener') which means element"create" can not be got.

I wonder how to solve this problem or any other ways to implement the same approach.

Sean.L
  • 33
  • 5
  • So that means the element does not exist. So you need to bind the element after you add it to the DOM. – epascarello Apr 14 '23 at 14:44
  • If you are going to fetch the html anyway, use a link and send the user to the form. If you don't want that you need to put both forms in the html and hide/show the forms as needed, fetching the whole html and then using innerHTML is overly complicated for nothing, a diplay:block/display:none will perform way better and without network latency – Lk77 Apr 14 '23 at 14:45
  • 1
    @HereticMonkey, this is more about waiting for the fetch to complete than binding to new elements. – isherwood Apr 14 '23 at 14:48
  • @isherwood So you think using event delegation wouldn't work in this case? AFAICT, binding to an ancestor element and examining the bubbled event targets would work swimmingly here... but feel free to propose a different duplicate, as there are duplicates for that eventuality as well. – Heretic Monkey Apr 14 '23 at 14:50
  • 1
    You have a `then` function which updates form.innerHTML. That would be the right place to assign an event listener to something in that updated html. Can’t tell where your event listener is currently being assigned but I bet it’s happening prior to the html being updated. – James Apr 14 '23 at 14:51
  • @HereticMonkey, on second thought that would probably work. It doesn't seem as elegant somehow, maybe since events will be processed when there's no element available. Either way should work. – isherwood Apr 14 '23 at 15:23

0 Answers0