new Angular file-reader component
authorGalen Charlton <gmc@equinoxinitiative.org>
Fri, 8 Nov 2019 23:39:34 +0000 (18:39 -0500)
committerGalen Charlton <gmc@equinoxinitiative.org>
Thu, 16 Jan 2020 21:38:28 +0000 (16:38 -0500)
This adds a ControlValueAccessor wrapper around a file
reader form input. Any file loaded via that input is interpreted
as a text file whose lines are to be split into an array on
newlines, with leading and trailng whitespace removed.

Usage is:

<eg-file-reader [(ngModel)]="fileContents">
</eg-file-reader>

Signed-off-by: Galen Charlton <gmc@equinoxinitiative.org>
Open-ILS/src/eg2/src/app/share/common-widgets.module.ts
Open-ILS/src/eg2/src/app/share/file-reader/file-reader.component.html [new file with mode: 0644]
Open-ILS/src/eg2/src/app/share/file-reader/file-reader.component.ts [new file with mode: 0644]

index 01b16bd..0f9abd8 100644 (file)
@@ -14,6 +14,7 @@ import {DateSelectComponent} from '@eg/share/date-select/date-select.component';
 import {OrgSelectComponent} from '@eg/share/org-select/org-select.component';
 import {DateRangeSelectComponent} from '@eg/share/daterange-select/daterange-select.component';
 import {DateTimeSelectComponent} from '@eg/share/datetime-select/datetime-select.component';
+import {FileReaderComponent} from '@eg/share/file-reader/file-reader.component';
 
 
 @NgModule({
@@ -24,6 +25,7 @@ import {DateTimeSelectComponent} from '@eg/share/datetime-select/datetime-select
     OrgSelectComponent,
     DateRangeSelectComponent,
     DateTimeSelectComponent,
+    FileReaderComponent,
   ],
   imports: [
     CommonModule,
@@ -43,6 +45,7 @@ import {DateTimeSelectComponent} from '@eg/share/datetime-select/datetime-select
     OrgSelectComponent,
     DateRangeSelectComponent,
     DateTimeSelectComponent,
+    FileReaderComponent,
   ],
 })
 
diff --git a/Open-ILS/src/eg2/src/app/share/file-reader/file-reader.component.html b/Open-ILS/src/eg2/src/app/share/file-reader/file-reader.component.html
new file mode 100644 (file)
index 0000000..d938bf6
--- /dev/null
@@ -0,0 +1 @@
+<input type="file" (change)="changeListener($event)" />
diff --git a/Open-ILS/src/eg2/src/app/share/file-reader/file-reader.component.ts b/Open-ILS/src/eg2/src/app/share/file-reader/file-reader.component.ts
new file mode 100644 (file)
index 0000000..4cbe5de
--- /dev/null
@@ -0,0 +1,62 @@
+/**
+ * <eg-file-reader [(ngModel)]="fileContents">
+ * </eg-file-reader>
+ */
+import {Component, OnInit, Input, Output, ViewChild,
+    TemplateRef, EventEmitter, ElementRef, forwardRef} from '@angular/core';
+import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
+import {Observable, of, Subject} from 'rxjs';
+import {map, tap, reduce, mergeMap, mapTo, debounceTime, distinctUntilChanged, merge, filter} from 'rxjs/operators';
+
+@Component({
+  selector: 'eg-file-reader',
+  templateUrl: './file-reader.component.html',
+  providers: [{
+    provide: NG_VALUE_ACCESSOR,
+    useExisting: forwardRef(() => FileReaderComponent),
+    multi: true
+  }]
+})
+export class FileReaderComponent implements ControlValueAccessor, OnInit {
+
+    // Stub functions required by ControlValueAccessor
+    propagateChange = (_: any) => {};
+    propagateTouch = () => {};
+
+    ngOnInit() {
+    }
+
+    changeListener($event): void {
+        const me = this;
+        if ($event.target.files.length < 1) {
+            return;
+        }
+        const reader = new FileReader();
+        reader.onloadend = function(e) {
+            me.propagateChange(me.parseFileContents(reader.result));
+        };
+        reader.readAsText($event.target.files[0]);
+    }
+
+    parseFileContents(contents): Array<string> {
+        const values = contents.split('\n');
+        values.forEach((val, idx) => {
+            val = val.replace(/\s+$/, '');
+            val = val.replace(/^\s+/, '');
+            values[idx] = val;
+        });
+        return values;
+    }
+
+    writeValue(value: any) {
+        // intentionally empty
+    }
+
+    registerOnChange(fn) {
+        this.propagateChange = fn;
+    }
+
+    registerOnTouched(fn) {
+        this.propagateTouch = fn;
+    }
+}