Need some help understanding how to extend a JavaScript class
To start, I did read this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends
But there is almost nothing there that I understand or recognize enough as something familiar that I can latch onto, so that's not really helpful.
All I'm trying to achieve is similar functionality to what this PHP example would do:
I'm having a lot of trouble understanding how I'm supposed to make JavaScript work like that, with the shared properties and methods. I figured it'd be pretty similar to set up, but it's clearly not, and I'm really stumped. I have no idea where to start. If anyone could shed some light on this, that would be great.
Thanks.
70 Replies
not gonna lie, you won't find because the php example is not exactly correct
Animal::__construct("squeak"); <-- i wouldn't do this, but would do parent::__construct instead
which is the same as super()
all methods and properties are public, unless you add # then it's private
oh, by the way, the php example would need to be an abstract class and the constructor should be private, which you can't do in jsi mean i pulled something quick out of my ass just to illustrate what i'm trying to make Javascript do, i wouldn't actually use that code for anything
okay, i guess i went too deep then
well, js doesn't have protected properties or methods: either public or private
so, yeah, you can't do exactly that
what i actually have are two classes that are going to need to use nearly all of the same properties and some of the same methods, and it makes the most sense to establish those properties/methods in a base class, but i can't figure out how to extend that base class so the child can use those properties and methods for what it needs to do with them
i'm probably explaining that poorly
just like in php, you should use
this. with them
as long as they are publicnot what this question is supposed to be about, but what is actually the difference between
ClassName::__construct() and parent::__construct() since you've mentioned it? they seem to work identically when extending thingsreplace
animal with quadrupede_mammal and you will understand it quickly
your original version sorta makes an hard dependency on animal
and you also need to remember to change the constructor later on
but what if you forget?OH okay so it's just if i decide i want to change the names of things at a later date, ok, that makes sense
lets just say you're supposed to call the constructor of your parent, not a specific class
what's the parent? it doesn't matter
you should get that habbit
well, the child classes extend a specific parent, so the parent in question does seem like it matters? like, if i change the name of the parent, i would still need to go through and update what the children extend, but that aside if it's best practice to use
parent::__construct() then that's what I'm going to start doing
that being said though
it turns out i couldn't extend my js class, because, for some reason, i did not realize i needed to import ityeah
that's the
use in phpi thought it was telling me my whatever wasn't defined because i was just extending wrong, turns out, no, it just couldn't find the file
with an autoloader
it is something super weird, in my opinion, but kinda makes sense
i hate when the problem turns out to be something as basic as "did you link it" lmao makes me feel so dumb
Is this what you're looking for?
i might still be dumb though, i need to make sure things are doing what i expect them to do
eeeh i feel bad you went ahead and wrote that for me hslfjks thank you; the php example i provided is actually really, really different from what i'm actually trying to do.
i was just trying to show that i wanted a base class to establish properties and methods for other classes to use, but discord only lets me have so many characters, and i could not get anything to work because it turned out i just never imported the class from the file it lives in. I thought there was something broken or something I was just entirely missing (it turned out yes but not anything anyone would be able to tell me about based on the information I provided)
Hey, you figured it out ! That's the important thing
ok yeah i do officially have it figured out, i just finished nestling all the shared items into a base class and finished up roughly half of what i need this upload form to do with no issues. Thank you both for the help, I'm sorry I'm so bad at explaining the problem
don't worry, the important is that you managed to do what you wanted
Not to be stack overflow but since you seem to be new, i'd like to warn you that classes and especially class inheritance is almost always a more complicated solution to something you can solve more elegantly in other ways. If you really need to use inheritance for some reason then go ahead, but especially in javascript, oop isn't very popular and sometimes even seen as an anti-pattern. Since you didn't provide a real code example I don't know if inheritance makes sense for your use case but i find almost always it's not actually needed and just overcomplicates things. So just be weary. I wasted a lot of time trying to solve problems the OOP way until i finally dropped it and became a much better and productive programmer
Since it was brought up, here's a brief tutorial on factory functions and how to use spread syntax to mimic class and inheritance but without needing to use the
new keyword (and I avoid this as much as I can as well). With modern JS engines the difference between prototypal inheritance and multiple instances of the same method via factory function is negligible—unless you're writing a game that excpects to run at 60+ FPS then the speed difference becomes important due to framerate considerations.
Now, since we're using a closure around the noise parameter in the makeAnimal factory function it's not accessible outside that specific function, so if you wanted to be able to use it in the rat function, you'd have to do something like this:
And BOOM! Another closure making noise accessible to the rat function without exposing it to the outside world. Of course, if you don't mind it being accessible/modifiable then you can add it as a property of the makeAnimal return value:
Or, even better, you can use a getter to get the value but not set it:
And using this method you can chain multiple different object "prototypes" together to create one mega-object!
And, since it's using the spread syntax, any method/property of later objects that share the same name as one from an earlier object will overwrite it, so if there's a specific version of a method you need tack it on the end. It's like method overloading, but not :pwon't this break the principle of substitution?
an in, something that takes the result of
makeAnimal also must accept the result of makeRatNot sure how it would break said principle. The
makeRat has all the methods of makeAnimal plus a few more
-# Though I'm not very well versed in the substitution principle so I could be wrongbut it isn't an instance of
Animal
it's just a copyAnd? It's still an animal, just not a
class-based one
It walks like a duck and talks like a duck. Ergo, duck :por a platipus
im just asking because the prototype will be different
Basically i have a handful of products that have varying amounts of spec sheets/installation manuals associated with them in the form of pdfs. I don't want to provide 40+ input sections per pdf type out the gate when the form is initially created because that's incredibly unwieldy and not always necessary, so i needed my javascript to be able to send a fetch request back to PHP for n more slots at will. To do this, it needs the csrf token of course, but it also needs to know which company the current product being built belongs to because each company's product form needs to be configured a little differently, and how many sections are currently already on the page.
When i finally properly upload the form after it's filled out, it, again, is going to need the token, the company, and the amount of file slots with something in them, because the plan, what with so much data, is to iterate through the list of one by one, until all the pdfs are in the pdf directory, and the database has everything organized. So the inheritance is from 1 base class that establishes the properties and methods required to call more form sections, and then upload the final data.
So like i said, extremely different code in reality, it just wasn't doing anything at first because nothing that should've been inherited was defined and i couldn't figure out why
Frame challenge: have a set 5 or 10 file inputs and require them to submit multiple forms at a time. That way each paylod is smaller and more likely to go through. Sure, it's more work for them, but it also is more resiliant to failure. Trying to upload 40 files at once can be difficult, so you're making them paginate the uploads instead of your code doing it. Also, they can batch the uploads and do a few at a time and come back later to finish
basically, like a wizard?
Yeah, basically
You're a wizard, epic!
i almost look like hagrid 🤣
but seriously, even if it isn't a wizard, you can make it a lot easier by just asking the basic info, then having an area for the files
Then again, you could have one file input with multiple select enabled:
yeah, but the files are uploaded in sequence, instead of you uploading multiple files
also, you will hit the upload limit a lot faster
instead of the upload limit being by file, it's for all files
because of the maximum size of the $_POST variables
That's also true, yeah. So I go back to my prior "set 5 or 10 file inputs"
or an upload queue
and then have 1-4 uploads at a time, maybe handled by a worker
actually, no workers needed, but a lot of nasty js code
if you want progress
I'm weary of an upload queue because people are dumb. They'll close the window before the queue is empty >_>
window.onunload = _ => 'there are still files in the queue. are you sure?'
there are other ways to do it, like adding a notification at the top showing progress, if possibleThe files also each have links to them that need to be human readable that are usually the associated part's number, a short sentence of info to be displayed with it, and part numbers specific to that manual, that i cant generate from the filename because it's junk, and that all need to be present when they come out the other side on the actual website, so they need to be entered with that pdf; i can't just upload a bunch of files and nothing else.
I also very much am planning to have indicators and preventatives in place; part of why i need that input list shared between the two classes is so when the uploader's moved onto the next one, it can also visually remove what's been uploaded already from the page, and mark the current focus as uploading. The only other two people who are going to be using this system besides me absolutely need it lol.
Also when i say im doing a file at a time, i do mean I'm doing a queue; the request starts, php handles the post variable, it ends, and js receives a message about it to signal the server is ready for the next, so js makes a new request, php handles that post variable, and so on, until js sees it's at the end, and sends a "done" signal to the server so the server knows to send a finished message to be displayed back when the last one's up. If there's an exception for whatever reason because the server couldn't deal with a file, i still need to figure out what I'll do about it, but I'll approach that later, i just need it to work at all first. There are rollbacks in place.
I am already planning to have it send basic info first to get the product entry into the database at all, because it's going to need the database id for that product in order to tie both manual and product together in a junction table. Manuals/sheets are also sometimes shared between products so the junction table is necessary.
It's a lot I've had to think about already and I'll likely have to revise something somewhere, but I'll do it as it comes
I'm trying to make it work first, and then im adding all the convenience features like visual indicators of progress and such
I also keep saying i need them shared; all that's really shared is the property, and the function that sets it. The two child classes are using that property in very different ways, but it's ultimately the same data, i just didn't see a reason to write both the method and the property twice when i could just extend. The parent class also has properties for the csrf token and the company dropdown, which are also used by both children. I didn't want everything in one class because they're technically doing different jobs--one builds and adds to the form, the other sends the inputs off--and when code gets too long it gets really hard to find things
This feels like an X/Y problem: you have
X problem and think Y is the solution so you ask about Y instead of X.
Do you have a minimal example you can put up on codepen or something so we can see better what you’re after? I think I have about 73% of the picture
Then again, you did say above that you figured out it so…maybe not worth the effort :pI mean i can make an attempt but all that actually exists and works right now are:
- Selecting a company, and receiving that company's product upload form on the change event
- entering a number between 1 and 20 in a field, pushing a button, and receiving that many more form fields to upload more entries of that particular pdf type lol
Everything else is still just plans in my head, but I've done form handling stuff before, it's just the way im going to be handling the pdfs here specifically that's new (and also class extension in javascript is new too lol but that's been sorted)
For the first item, I would have all the upload forms in the HTML but hidden by default. Use the target pseudo-class to show the correct form.
That way there’s no extra processing to do, no extra HTTP calls. It’s all just there.
For the second point, I would have a template for the upload fields and an object in memory used to decide, based on the url id, which to use. The JS would then be in charge of populating the correct number of upload fields to the form.
I should mention, a lot of the choices here are being dictated by the fact this website already exists, it's just a static site with no database at all, and the person who actually owns it wants it to stay as close to what it currently looks like as it can
I’m at work and about to hit the road (Amazon delivery driver) but if you can write out some basic requirements and example upload fields I should be able to knock out a version for you to look at and maybe get inspired by when I get home in ~9hrs
I'll see what i can do, thank you so much. Also drive safe, idk what your weather is like but my area got slammed with snow this morning, hopefully your roads are fine
Ohio, USA. So yeah, roads are 💩
Oof, same lol
We should meet up for ☕ then! Warm up lol
that could be nice lol
So this website is for a small business that distributes products for 3 other companies.
The first company sells intercom systems for apartment buildings, and emergency/nurse calls for hospitals and retirement homes. The second sells apartment style mailboxes, and the third sells door strikes.
So, all very different, but it makes sense to distribute them together.
The first company has 3 webpages dedicated to it, one per product type. Each product type has 2-5 different models, and each model has a product brochure and submittal package, a handful (2-10) of installation manuals, and anywhere from 5-40 or so specification sheets. The spec sheets are for the different components that make up the product--so like, speakers, buttons, pull cords, etc. Both manuals and spec sheets are displayed in the same format, with the part number (that's also a link to the manual/sheet), the booklet's topic, and manual number. So:
CM800 - Pull cord, 12", with drawing - IL087
Not a real entry, but that's what they look like.
Because there are so many sheets, there's an anchor link you can click while viewing the most basic info to jump to the associated spec sheet section toward the bottom of the page.
All 3 of this company's product types are organized like this, so they use the same template, but the route tells the server which set of products to put on that template.
Or, it will. I have it loading test data right now since the database has nothing in it.
The other two companies have significantly less going on; mailbox co sells 4 types of mailboxes, each mailbox has a few captioned photos, some basic product info, and 2 pdf links per box. Door strike co has 3 strike types, but again, there is a varying amount of pdf links, though it's nowhere near as nutty as what's going on with the intercom company. Each strike also comes with a reference table that contains wiring/electrical information.
So that... is what I'm trying to sort into some level of sanity rn lol.
An alternative solution i've been thinking about is, have a page in the back that's dedicated to uploading PDF files and their associated information, and then upload product info wholly separate, and while on that screen have a bunch of checkboxes or something so you can choose which pdfs belong to that product
but that seems like it'd be extremely easy to accidentally neglect adding one, and there are so many I don't think anyone would catch it until customers complain
you could argue it'd be easy to accidentally add duplicates too, if you upload PDFs and products together, but if an entry already exists in the database for that pdf, i can use the manual ID to sniff it out and just discard that upload in favor of using the one that already exists
I dunno, it's a lot of stuff. It's probably less complicated than I'm making itIt's hideous at the moment, but this is the current iteration of the "add product" form for the intercom/nurse call/emergency call company. There is one additional menu at the top that's cut off--that is the selection menu for the company. The other two companies don't have forms yet--I'm dealing with this one first since it's the most complex



I need to change some of those labels, they suck
I literally made this whole thing last night, there's a lot that isn't staying the same here, in terms of some of the wording/presentation
When you first load the page, it looks like this. There's quite literally nothing there until you choose something from the dropdown menu. If you were to choose another company after filling out some of the form for another, it will overwrite the current form, so I will be adding a pop up that asks if you're sure, if i even keep this

gonna throw a version of the js in a codepen, though it can't work without being able to talk to the server
not gonna lie, that's very ... dense
and one of the child classes requires a dependency injection from php
yeah, i... i know, aha. i badly want it to be less... that
i can see someone getting lost in no time
yeah same, it's something i was going to deal with after i had something that worked at all
which is fine
originally i had it sending like, 10 pdf slots to start and when i looked at the actual output i was given i just frowned and immediately turned it down to one each
the "ask for more stuff" button is at the bottom of the list, and a new slot is inserted between the div that contains that button, and the last div that contains the existing pdf file upload inputs, so i thought until i think of something better just adding a new slot as you finish entering data would be the best way to go about it
i hate how bad i am at explaining things; i requested another slot and then turned it yellow--that's where new inputs get added, above the button/input field, but under what already exists

that is a very meh ui, not gonna lie
structurally every new field that gets added also has its own ID/labels too; it's not just sending the same piece of html repeatedly

yeah no i hate it lol, like i said, i made it last night so there's a lot that isn't staying the same, i just need it to work
the names in the HTML there probably aren't going to be used, i set that up before i had the realization that sending every PDF at the same time is probably a bad idea
the labels are inside the <h4> and <h3> headings, i just realized you can't actually see them
here's something i whipped out in excalidraw

I'll see if I can get something that looks like that working, that would definitely be significantly better
thank you
i figure there's a library somewhere for the file drop part but i'm going to try following the material for that i found on mdn
oh, yeah, there's lots of bullshit that needs to be done
So that old mess looks like this new mess now. I couldn't get the drag/drop working because there are two of these upload spots on the page.
It works fine when there's just one, but it gets confused and won't let me drop to either of them when there's two, and I understand why it's doing that, but I have absolutely no idea what I'm supposed to do about it.
Listening for the change event is probably good enough here anyway; as much as I'd like to fix it, I don't think any of us are going to be doing much dragging/dropping in the first place.
Also it is no longer sending requests to the server for more form pieces lol

I will be adding a little "X" button somewhere on those cards to remove individual files from the queue
probably should add a "clear all" button too
don't forget to add a
title attribute, so people can still see the whole name of the file
if you do, make sure the user has to confirm the actionYeah really annoying when text cuts off bef...
Ah yeah that's there! You just can't see it lol