avatarAmelie Bauer

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>

Why college is a scam but also crucial

My personal experience after my first semester of college

Photo courtesy of Unsplash.

After immersing myself into the college life starting in August of this year, I now have acclimated to the environment and know what it is like to be a full time student. I entered college as a Biochemistry major with the intent to go into research after college. Obviously being a freshman and 18 years old I understood that this plan could always change in a blink of an eye. From what I have heard from those around me, its pretty typical to change your major around three times. Now, after one semester of college I am already looking at changing my major.

To give some perspective, my course load from this past semester consisted of Foundations of Chemistry, Chemistry lab and recitation, Calculus 1, Moral Conflicts and Ethics, and Women in Religion. I took a total of 16 credit hours. I would spend many hours during the week studying mainly for my Chemistry and Calculus classes. I would rush through my non-STEM classwork in order to get to my STEM classwork. I easily half-assed my non-STEM classes, yet I passed these classes with an A. Take a second and guess what I got in my STEM classes that I spent easily over 30 hours a week doing work for…ready…I got a B in Chemistry and a D in Calculus. A major hit to my GPA and bank account since I didn’t pass my Calculus class.

In high school I sat at the top of my class with As and Bs. Now, I am struggling to scrape by Calculus with a C. Knowing that I spent a great deal of time studying for this class, would do the homework with the intent of learning and comprehending, utilize study groups and ask questions in class I was confused on how I could barely pass a midterm exam, let alone the class. I had done everything I could to learn the material and would change my study methods after each exam in the hopes of improving my exam score. My fault was not being able to take an exam well enough to pass it. I also struggled with this in Chemistry, but not to the same extent as I did in Calculus.

It has become increasingly normalized to walk into college and start out by taking increasingly difficult classes without having any experience in the college environment. A big part in doing well in classes is not only the effort that is put in, but also understanding how the class works. It takes a while to understand how college classes are different than high school classes. It also takes a while to adjust to the idea that as a college student, you will have to teach yourself the content. It seemed that the professors were there to instruct and introduce the ideas, but as the student your job was to read up on the subject then work to break down the components of the subject on your own.

I believe this is a flaw in the college system. While classes are structured differently, there is no “intro to college” class that teaches educational independence and how to adequately teach oneself in college level classes, so why is it expected of student to teach themselves a large part of the curriculum they are paying the University to learn?

I had a friend whose computer science professor left so many gaps in their teaching that my friend stopped going to lectures all together because it was easier for them to teach themselves rather than spend time confused by what the professor was discussing or not discussing in class.

It seems that taking the time to teach oneself has become normalized in college, which may be reasonable, but I feel like it may also be a red flag in the college educational system.

My other question is why it is normalized to jump right into incredibly difficult and rigorous classes freshman year? While I may have chosen a more rigorous major to enter college under, I feel that immediately starting with Calculus and Chemistry for Biochem majors was not the best idea. This can fall back on me as a personal mistake that I have made, but it was also communicated to me by my academic advisor that these courses were common for incoming STEM major freshman. I feel that if I were directed to take a prerequisite for Calculus then I would not have found myself with a D.

Photo courtesy of Unsplash.

I have always had a more creative and writing brain compared to a super analytical and mathematic brain. I also genuinely enjoy classes and concepts that are more conceptual and allow out of the box thinking. This meaning that I perform exceptionally better on written or verbal exams and through papers. Now that I have barely scraped by in Chemistry with a B and failed Calculus, I am reconsidering my major and what I may be interesting in pursuing as my future career. My question is, what would have happened if I passed Calculus with a C and then went on to take Organic Chemistry and Calculus 2 next semester? I think I would have found myself deep in the STEM hole and had a hard time rationalizing the idea of switching to a non-STEM major since I would have been decently far into my major’s required classes.

Luckily, failing Calculus was a blessing in disguise as I am now able to explore the idea of taking a variety of classes next semester to begin to understand what I may have a interest in.

Unfortunately, if I do switch to a non-STEM major, the classes that I have taken in STEM would not typically help me towards my non-STEM degree. My problem with this is college digging you into a hole where when you enter college you must be locked in on your career path. I know many people have different experiences with college and their major, but I think the normalization of throwing a student into high level classes their first semester creates chaos in the sense that it could lock that person into their major to the point where they feel like they cannot switch out of it because of all the money they have already contributed to their major specific classes. Not to mention the fact that someone could be years into college and decide that the path they were going down isn’t for them, then they are theoretically forced to start over, which most people cannot financially justify.

College is incredibly crucial in order to put oneself in an optimal spot to qualify for high paying jobs, but it does also present very scam-like aspects to its character.

Luckily, I have realized early on in my college experience that I need to explore alternate career fields, but my concern is what if I had already been a year or two into my Biochemistry major and then hit a point where I couldn’t pass any of my classes no matter how hard I tried and had to reconsider then. I believe the structure of college is not suited for the student and exploration process as well as it could be. I also feel that the normalization of self-teaching and rigorous classes in the STEM major specifically is a flaw in the college educational system.

College is a privilege I am incredibly grateful to have the opportunity for and am grateful to have the resources to switch my intended major if I wanted.

If you enjoyed this piece, take a look at some of my other articles below!

College
Perspective
Career Advice
Careers
College Life
Recommended from ReadMedium