avatarBenjamin Davis

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

7759

Abstract

component template how the upload blue button and the invisible file input are linked. When the user clicks on the blue button, a click handler triggers the file input via <code>fileUpload.click()</code>.</p><p id="ac29">The user will then choose a file from the file upload dialog, and the <code>change</code> event will be triggered and handled by <code>onFileSelected()</code>.</p><h1 id="7571">Uploading a file to the backend using the Angular HTTP Client</h1><p id="fff6">Let’s now have a look at our component class and the implementation of <code>onFileSelected()</code>:</p><div id="98fa"><pre><span class="hljs-meta">@Component</span>({ <span class="hljs-attr">selector</span>: <span class="hljs-string">'file-upload'</span>, <span class="hljs-attr">templateUrl</span>: <span class="hljs-string">"file-upload.component.html"</span>, <span class="hljs-attr">styleUrls</span>: [<span class="hljs-string">"file-upload.component.scss"</span>] }) <span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">FileUploadComponent</span> {

fileName = <span class="hljs-string">''</span>;

<span class="hljs-title function_">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> http: HttpClient</span>) {}

<span class="hljs-title function_">onFileSelected</span>(<span class="hljs-params">event</span>) {

    <span class="hljs-keyword">const</span> <span class="hljs-attr">file</span>:<span class="hljs-title class_">File</span> = event.<span class="hljs-property">target</span>.<span class="hljs-property">files</span>[<span class="hljs-number">0</span>];

    <span class="hljs-keyword">if</span> (file) {

        <span class="hljs-variable language_">this</span>.<span class="hljs-property">fileName</span> = file.<span class="hljs-property">name</span>;

        <span class="hljs-keyword">const</span> formData = <span class="hljs-keyword">new</span> <span class="hljs-title class_">FormData</span>();

        formData.<span class="hljs-title function_">append</span>(<span class="hljs-string">"thumbnail"</span>, file);

        <span class="hljs-keyword">const</span> upload$ = <span class="hljs-variable language_">this</span>.<span class="hljs-property">http</span>.<span class="hljs-title function_">post</span>(<span class="hljs-string">"/api/thumbnail-upload"</span>, formData);

        upload$.<span class="hljs-title function_">subscribe</span>();
    }
}

}</pre></div><p id="efe8">Here is what is going in this component:</p><ul><li>we are getting a reference to the files that the user selected by accessing the <code>event.target.files</code> property.</li><li>we then build a form payload by using the <code>FormData</code> API. This is a standard browser API, it's not Angular-specific.</li><li>we then use the Angular HTTP client to create an HTTP request and send the file to the backend</li></ul><p id="8224">At this point, we would already have a working file upload component. But we want to take this component one step further. We want to be able to display a progress indicator to the user, and also support upload cancelation.</p><h1 id="2e9b">How to Display a File Upload Progress Indicator</h1><p id="0abb">We are going to add a few more elements to the UI of our file upload component. Here is the final version of the file upload component template:</p><div id="2cff"><pre><input <span class="hljs-keyword">type</span>=<span class="hljs-string">"file"</span> <span class="hljs-keyword">class</span>=<span class="hljs-string">"file-input"</span> [accept]=<span class="hljs-string">"requiredFileType"</span> (change)=<span class="hljs-string">"onFileSelected($event)"</span> #fileUpload>

<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"file-upload"</span>></span>

{{fileName || "No file uploaded yet."}}

<span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">mat-mini-fab</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"primary"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"upload-btn"</span>
  (<span class="hljs-attr">click</span>)=<span class="hljs-string">"fileUpload.click()"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">mat-icon</span>&gt;</span>attach_file<span class="hljs-tag">&lt;/<span class="hljs-name">mat-icon</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

<span class="hljs-tag"></<span class="hljs-name">div</span>></span></span>

<span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"progress"</span>></span>

<span class="hljs-tag"><<span class="hljs-name">mat-progress-bar</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"progress-bar"</span> <span class="hljs-attr">mode</span>=<span class="hljs-string">"determinate"</span> [<span class="hljs-attr">value</span>]=<span class="hljs-string">"uploadProgress"</span> *<span class="hljs-attr">ngIf</span>=<span class="hljs-string">"uploadProgress"</span>></span>

<span class="hljs-tag"></<span class="hljs-name">mat-progress-bar</span>></span>

<span class="hljs-tag"><<span class="hljs-name">mat-icon</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"cancel-upload"</span> (<span class="hljs-attr">click</span>)=<span class="hljs-string">"cancelUpload()"</span> *<span class="hljs-attr">ngIf</span>=<span class="hljs-string">"uploadProgress"</span>></span>delete_forever<span class="hljs-tag"></<span class="hljs-name">mat-icon</span>></span>

<span class="hljs-tag"></<span class="hljs-name">div</span>></span></span></pre></div><p id="6548">The two main elements that we have added to the UI are:</p><ul><li>An Angular Material progress bar, which is visible only while the file upload is still in progress.</li><li>A cancel upload button, also only visible when an upload is still ongoing</li></ul><h2 id="8e22">How to know how much of the file has been uploaded?</h2><p id="318b">The way that we implement the progress indicator, is by using the <code>reportProgress</code> feature of the Angular HTTP client.</p><p id="7c34">With this feature, we can get notified of the progress of a file upload via multiple events emitted by the HTTP Observable.</p><p id="8436">To see it in action, let’s have a look at the final version of the file upload component class, with all its features implemented:</p><div id="88a0"><pre><span class="hljs-meta">@Component</span>({ <span class="hljs-attr">selector</span>: <span class="hljs-string">'file-upload'</span>, <span class="hljs-attr">templateUrl</span>: <span class="hljs-string">"file-upload.component.html"</span>, <span class="hljs-attr">styleUrls</span>: [<span class="hljs-string">"file-upload.component.scss"</span>] }) <span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">FileUploadComponent</span> {

<span class="hljs-meta">@Input</span>()
<span class="hljs-attr">requiredFileType</span>:<span class="hljs-built_in">string</span>;

fileName = <span class="hljs-string">''</span>;
<span class="hljs-attr">uploadProgress</span>:<span class="hljs-built_in">number</span>;
<span class="hljs-attr">uploadSub</span>: <span class="hljs-title class_">Subscription</span>;

<span class="hljs-title function_">constructor</span>(<span class="hljs-

Options

params"><span class="hljs-keyword">private</span> http: HttpClient</span>) {}

<span class="hljs-title function_">onFileSelected</span>(<span class="hljs-params">event</span>) {
    <span class="hljs-keyword">const</span> <span class="hljs-attr">file</span>:<span class="hljs-title class_">File</span> = event.<span class="hljs-property">target</span>.<span class="hljs-property">files</span>[<span class="hljs-number">0</span>];
  
    <span class="hljs-keyword">if</span> (file) {
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">fileName</span> = file.<span class="hljs-property">name</span>;
        <span class="hljs-keyword">const</span> formData = <span class="hljs-keyword">new</span> <span class="hljs-title class_">FormData</span>();
        formData.<span class="hljs-title function_">append</span>(<span class="hljs-string">"thumbnail"</span>, file);

        <span class="hljs-keyword">const</span> upload$ = <span class="hljs-variable language_">this</span>.<span class="hljs-property">http</span>.<span class="hljs-title function_">post</span>(<span class="hljs-string">"/api/thumbnail-upload"</span>, formData, {
            <span class="hljs-attr">reportProgress</span>: <span class="hljs-literal">true</span>,
            <span class="hljs-attr">observe</span>: <span class="hljs-string">'events'</span>
        })
        .<span class="hljs-title function_">pipe</span>(
            <span class="hljs-title function_">finalize</span>(<span class="hljs-function">() =&gt;</span> <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">reset</span>())
        );
      
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">uploadSub</span> = upload$.<span class="hljs-title function_">subscribe</span>(<span class="hljs-function"><span class="hljs-params">event</span> =&gt;</span> {
          <span class="hljs-keyword">if</span> (event.<span class="hljs-property">type</span> == <span class="hljs-title class_">HttpEventType</span>.<span class="hljs-property">UploadProgress</span>) {
            <span class="hljs-variable language_">this</span>.<span class="hljs-property">uploadProgress</span> = <span class="hljs-title class_">Math</span>.<span class="hljs-title function_">round</span>(<span class="hljs-number">100</span> * (event.<span class="hljs-property">loaded</span> / event.<span class="hljs-property">total</span>));
          }
        })
    }
}

<span class="hljs-title function_">cancelUpload</span>(<span class="hljs-params"></span>) { <span class="hljs-variable language_">this</span>.<span class="hljs-property">uploadSub</span>.<span class="hljs-title function_">unsubscribe</span>(); <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">reset</span>(); }

<span class="hljs-title function_">reset</span>(<span class="hljs-params"></span>) { <span class="hljs-variable language_">this</span>.<span class="hljs-property">uploadProgress</span> = <span class="hljs-literal">null</span>; <span class="hljs-variable language_">this</span>.<span class="hljs-property">uploadSub</span> = <span class="hljs-literal">null</span>; } }</pre></div><p id="6e91">As we can see, we have set the <code>reportProgress</code> property to true in our HTTP call, and we have also set the <code>observe</code> property to the value <code>events</code>.</p><p id="cbac">This means that, as the POST call continues, we are going to receive event objects reporting the progress of the HTTP request.</p><p id="294a">These events will be emitted as values of the <code>http</code> Observable, and come in different types:</p><ul><li>events of type <code>UploadProgress</code> report the percentage of the file that has already been uploaded</li><li>events of types <code>Response</code> report that the upload has been completed</li></ul><p id="aa3c">Using the events of type <code>UploadProgress</code>, we are saving the ongoing upload percentage in a member variable <code>uploadProgress</code>, which we then use to update the value of the progress indicator bar.</p><p id="ea5b">When the upload either completes or fails, we need to hide the progress bar from the user.</p><p id="b2ef">We can make sure that we do so by using the RxJs <code>finalize</code> operator, which is going to call the <code>reset()</code> method in both cases: upload success or failure.</p><h1 id="29cb">How to Cancel an Ongoing File Upload</h1><p id="d74e">In order to support file upload cancellation, all we have to is keep a reference to the RxJs Subscription object that we get when the <code>http</code> Observable gets subscribed to.</p><p id="aa0f">In our component, we store this subscription object in the <code>uploadSub</code> member variable.</p><p id="5ae9">While the upload is still in progress, the user might decide to cancel it by clicking on the cancel button. Then the <code>cancelUpload()</code> upload method is going to get triggered and the HTTP request can be canceled by unsubscribing from the <code>uploadSub</code> subscription.</p><p id="5e61">This unsubscription will trigger the immediate cancelation of the ongoing file upload.</p><h1 id="9aad">How to accept only files of a certain type</h1><p id="c8b0">In the final version of our file upload component, we can require the user to upload a file of a certain type, by using the <code>requiredFileType</code> property:</p><div id="8c53"><pre><span class="hljs-tag"><<span class="hljs-name">file-upload</span> <span class="hljs-attr">requiredFileType</span>=<span class="hljs-string">"image/png"</span>></span><span class="hljs-tag"></<span class="hljs-name">file-upload</span>></span></pre></div><p id="fe67">This property is then passed directly to the <code>accept</code> property of the file input in the file upload template, forcing the user to select a png file from the file upload dialog.</p><h1 id="a737">How to Upload Multiple Files</h1><p id="d62f">By default, the browser file selection dialog will allow the user to select only one file for upload.</p><p id="cb3a">But using the <code>multiple</code> property, we can allow the user to select multiple files instead:</p><div id="af5a"><pre><<span class="hljs-built_in">input</span> <span class="hljs-built_in">type</span>=<span class="hljs-string">"file"</span> <span class="hljs-keyword">class</span>=<span class="hljs-string">"file-upload"</span> multiple></pre></div><p id="a900">Notice that this would need a completely different UI than the one that we have built. A styled upload button with a progress indicator only works well for the upload of a single file.</p><p id="14d6">For a multi-file upload scenario, there are a variety of UIs that could be built: a floating dialog with the upload progress of all files, etc.</p><h1 id="f2f4">Summary</h1><p id="a227">The best way to handle file upload in Angular is to build one or more custom components, depending on the supported upload scenarios.</p><p id="b3e1">A file upload component needs to contain internally an HTML input of type file, that allows the user to select one or more files from the file system.</p><p id="e4ad">This file input should be hidden from the user as it’s not styleable and replaced by a more user-friendly UI.</p><p id="289e">Using the file input in the background, we can get a reference to the file via the <code>change</code> event, which we can then use to build an HTTP request and send the file to the backend.</p><p id="245e">Also, if you have some questions or comments please let me know in the comments below and I will get back to you.</p></article></body>

8 Awkward Steps in My Masturbation Education

Repressed parents, lousy porn, and horny friends led to an exceptionally awkward sexual awakening.

Photo by Peter F. Wolf on Unsplash

When I was in kindergarten, I used to lay in bed butt-naked, spread-eagle, and imagine girls from my class, falling on top of me through the ceiling. Then, we would hug each other very tightly and roll around. At this point, I’d never seen people have sex, nor had I seen porn. I just instinctually wanted a warm body against mine, never suspecting for a minute that this spout between my legs needed to be in any way involved. This weird habit aside, my interests were more in building forts, putting ketchup on chicken, and refusing to take off my blue power ranger outfit. Then, one dark night, everything changed.

Step 1: Just wrap your fingers around it and go up and down.

Sleepovers were the in-thing in the 90s. Without group texting, if I wanted to interact with my friends, this meant seeing them. I was seven or eight, and my best friend was named Joey. He was cooler than me. This isn’t saying much about Joey, though, since I was still refusing to take off my power ranger costume. It was the middle of the night, and I was almost asleep, tucked innocently beneath a blanket on one couch. At the same time, Joey lay, breathing heavy, on the other. I was almost in dreamland when I found myself shaken awake. Joey was standing over me, and he said:

“Have you ever masturbated before?”

“What?” I asked. And he smiled like adults smile when they find out you haven’t yet heard this really great band. (Yes, kids, surprises get worse and worse the older you get).

“You’ve gotta try it,” he said. He held up a finger, then used his ring and middle fingers to press it into his thumb. He started moving them up and down.

“Do that,” he said, “But — “ and this was the kicker, “with your penis.”

And I did.

Oh, boy, did I.

I don’t remember what happened to my blue power ranger outfit after that.

Step 2: There is more than one way to burp a baby worm

When people imagine men masturbating, they’re often picturing a man with a fistful of dick violently going up and down like it’s some sort of weird carnival game where, if they do it fast enough, money will shoot out the top. It’s not really like that — especially not when you’re a kid whose penis hasn’t grown into the size of your hands. Three fingers — that was how I learned. I didn’t realize anyone did anything different until kids started making masturbation jokes at school, using their whole fist to simulate the action. At first, I’d be like, “yeah!” and hold up my three dirty fingers without realizing anything wrong with it.

My cool streak lived on.

Step 3: The porn chooses the wizard

My mom always said that beggars can’t be choosers. That was never truer than when my friends and I managed to get ahold of porn. Sometimes it came from older brothers, sometimes from stashes, they found of their dad’s. I never discovered porn in my house, so I always had to rely on friends.

My first porn came as a VHS tape smuggled over by my friend Peter. We locked the door to the basement in the middle of the day, turned out all of the lights, and hit play. It was vampire fantasy porn. This was all well-and-good until we found out how the men were turned into vampires. Yes, they bit off their penises.

It was only after that moment that I turned to look at Peter and realized, to my horror, that he was masturbating…too.

Step 4: Masturbating together — no, not on a cookie

Whether it was 2, 4, or 7 young boys, it got to a point where no sleepover was complete without someone sneaking over a porn tape. And, no, boys don’t just watch it to comment on the physique. This stage, in particular always makes women I’ve told cringe.

“You really all masturbated in a room together?” they’ll ask.

“Yes.”

“Like on a cookie?”

What’s with the cookie thing? This was a viral rumor that occurred before the internet where people assumed that boys played a game where the last person to come on a cookie had to eat it. While most men I’ve talked to have experienced childhood group masturbation sessions, I have yet to meet a guy who said, “Oh, and remember doing the cookie thing?”

Also, many of my friends couldn’t actually produce semen when we started masturbating.

Step 5: Getting through the dry period

Yes, boys can masturbate and even orgasm before they can produce semen. Most of the boys I grew up with couldn’t come when they started. I miss it, actually. It was a cleaner time in my life — no dirty socks or crusty underwear or having to lean over a toilet. There was no gooey reminder of shame leftover. For the first few years of masturbating, I was unable to produce semen. What started as a convenience soon became something shameful. Other kids began to be able to produce semen, and it became a weird little test of manhood. I remember being at a friend’s house where we were masturbating over the back cover of some video game, and two of my friends ran to the bathroom. Feeling embarrassed, I went after them. When I came back, they asked, “Did you finally come!”

I was like, “Yeah! Oh, it was great.”

To be honest, it was good practice for my high school years when I’d lie and say, “Yeah, blowjobs…uh…totally feel great!”

Step 6: You end up doing it in weird places.

One day, it happens! The burp in your worm, the tartar sauce in your rainbow, the tears in your bald man’s eye. Now, where to put it? Everyone has their go-to spot. Someone sent me a post on Reddit once about a guy who did it in the same box over 10 years. Gross. Most boys go for a sock, or the smart ones have tissues beside the bed. In the end, there is no great place to put it, especially since it can pop up at the worst times. Horniness is a lot like hunger for a teenage boy. So imagine that you periodically get agonizingly hungry and are lucky enough to always be walking around with a bucket of chicken in your pants.

Yeah — you get the idea. I could list all of the places my teenage self shamefully masturbated, but this article would become an hour-long read. Basically, it’s gross. Just gross. That’s all I can say. And, eventually, someone catches you.

Step 7: Your parents eventually find out, and it’s weird

My mother has an uncomfortable sense of humor. She called “Bring It On” the masturbation movie. If I ever tried to watch it with my friends, she’d yell after us, “Ooo, you guys going to watch the masturbation movie!?”

It was a damn good movie, okay? Just that. Great acting. Spot on-camera work. Fantastic soundtrack. Really a first-rate flick. That’s all. Okay, mom?

And the day she walked into my room, burst out laughing, then slammed the door and called, “What were you doing?” I didn’t — did not, have the Bring It On VHS tape in bed next to me.

Step 8: Mastering the art of discrete masturbation

Eventually, masturbation becomes more of a habit than a need. Rogue boners come around less and less, and you meet someone who lets you do with them what you’ve been doing to yourself for years. I’ve never met a man who had an orderly unawkward experience learning to masturbate. It is always cringy, gross, and embarrassing. Some kids learn from family members. Others discover it for themselves. I’d imagine that these days many kids can just look it up. Some men I’ve met got way too comfortable with food when they were starting out. One guy even admitted an alarming hot-pocket incident to me.

The important thing is to be able to laugh at the absurdity of this process. I think I was lucky to have parents who at least never talked about it. Some kids are scolded or taught that it is awful or blasphemous. It’s not. It’s awkward, hilarious, and a part of growing up. Though, maybe if you are a sibling or parent of young boys, just don’t think about it too much — and remove all blacklights from the premises.

*also, doesn’t it totally look like that guy in the cover photo is shamefully masturbating behind some building?

Looking for more?

Humor
Sexuality
Self
Self Love
Life Lessons
Recommended from ReadMedium