Przeglądaj źródła

Updated docs for Angular Upload Adapter.

Maciej Bukowski 6 lat temu
rodzic
commit
5afd724fdb
1 zmienionych plików z 81 dodań i 103 usunięć
  1. 81 103
      docs/builds/guides/frameworks/angular.md

+ 81 - 103
docs/builds/guides/frameworks/angular.md

@@ -350,101 +350,100 @@ will be preferable in the case where there is more than one `<ckeditor>` element
 the page.  Also, if the `<ckeditor>` element is inside an `*ngIf` structure the `@ViewChild`
 declared variable may be inadvertently undefined.
 
-## Implementing an Upload Adapter in an Angular Application
+## Implementing an Upload Adapter in the Angular Application
 
-An Upload Adapter can be used with CKEditor so that when a user adds an image
-to a document it is encoded as a link to the image.  The image itself is stored
-separately from the document.   When images are large or numerous this results
-in noticable improvement in performance over the default behavior.  Read about custom
-UploadAdapters {@link framework/guides/deep-dive/upload-adapter here}.
+An Upload Adapter can be used with CKEditor 5 so that when a user adds an image
+to a document it is encoded as a link to the image. The image itself is stored
+separately from the document. When images are large or numerous this results
+in noticeable improvement in performance over the default behavior. Read about custom
+UploadAdapters {@link TODO framework/guides/deep-dive/upload-adapter here}.
 
-The first step is to create an Upload Adapter.  This can be done in the same file where the
-component that will use it.  Alternatively this can have its own file and be
-imported.
-
-This class will be instantiated each time that CKEditor needs it.  Note that
-the functions in this class will run outside an `NgZone` which means that
-if it makes changes to variables bound to HTML elements, the shadow-DOM logic
-in the Angular framework won't detect those changes.
-
-The instance property `loader` is the primary interface between the UploadAdapter
-and the CKEditor instance.
+If you're familiar with Angular you have probably already used the [`HTTPClient`](https://angular.io/guide/http)
+service which wraps the JavaScript XMLHttpRequest and provides a more concise API around it.
 
 ```ts
-class UploadAdapter {
-  private loader;
-  private url;
+import { Subscription, Observable } from 'rxjs';
+import { HttpClient, HttpEventType, HttpRequest, HttpEvent } from '@angular/common/http';
+// ...
 
-  private sub: Subscription;
+class UploadAdapterPlugin {
+	constructor( editor ) {
+		const httpClient = editor.config.get( 'httpClient' );
 
-  constructor(loader, url) {
-    this.loader = loader;
-    this.url = url;
-  }
+		editor.plugins.get( 'FileRepository' ).createUploadAdapter = loader => {
+			return new UploadAdapter( loader, httpClient, '/image' );  // Modify for your server.
+		};
+	}
+}
 
-  upload() {
-    return new Promise((resolve, reject) => {
-      const fd = new FormData();
-      fd.append('file', this.loader.file);
-
-      this.sub = this.httpPostMediaReq(fd).subscribe(
-        (event) => {
-          if (event.type === HttpEventType.Response) {
-            const resp = event.body;
-            if (!resp.list || resp.list.length < 1 || resp.list[0].id < 1) reject(resp.error);
-            else {
-              const imageURL = this.imageURL(resp.list[0].id);
-              resolve({ default: imageURL });
-            }
-          }
-          else if (event.type === HttpEventType.UploadProgress) {
-            this.loader.uploaded = event.loaded;
-            this.loader.uploadTotal = event.total;
-          }
-        },
-        (err) => {
-            reject(err.body.message);
-        });
-    });
-  }
+class UploadAdapter {
+	private sub: Subscription;
+
+	constructor(
+		private loader: any,
+		private httpClient: HttpClient,
+		private url: string
+	) { }
+
+	public upload() {
+		return new Promise( ( resolve, reject ) => {
+			const formData = new FormData();
+			formData.append( 'file', this.loader.file );
+
+			this.sub = this.httpPostMediaReq( formData ).subscribe( event => {
+				if ( event.type === HttpEventType.Response ) {
+					const response = event.body;
+
+					if ( !response.list || response.list.length < 1 || response.list[ 0 ].id < 1 ) {
+						return reject( response.error );
+					}
+
+					const imageURL = this.getImageUrl( response.list[ 0 ].id );
+					resolve( { default: imageURL } );
+				} else if ( event.type === HttpEventType.UploadProgress ) {
+					this.loader.uploaded = event.loaded;
+					this.loader.uploadTotal = event.total;
+				}
+			}, err => {
+				reject( err.body.message );
+			} );
+		} );
+	}
 
-  imageURL(id) {
-     // RETURN THE URL WHERE THE SUCCESSFULY UPLOADED IMAGE
-     // CAN BE RETRIEVED WITH AN HTTP GET REQUEST
-  }
+	public abort() {
+		if ( this.sub ) {
+			this.sub.unsubscribe();
+		}
+	}
 
-  httpPostMediaReq(formReq: FormData): Observable<any> {
-      const options: {
-        observe: 'events';
-        reportProgress: boolean;
-        withCredentials: boolean;
-      } = {
-        withCredentials: true,
-        reportProgress: true,
-        observe: 'events'
-      };
-      const request = new HttpRequest(
-        'POST', this.url, formReq, options);
-      return this.http.request(request);
-    }
-
-  abort() {
-    console.log('UploadAdapter abort');
-    if (this.sub) this.sub.unsubscribe();
-  }
+	private getImageUrl( id ) {
+		// Return the URL where the successfully upload image
+		// can be retrieved with an HTTP GET request.
+	}
+
+	private httpPostMediaReq( formData: FormData ): Observable<HttpEvent<any>> {
+		const request = new HttpRequest(
+			'POST',
+			this.url,
+			formData,
+			{
+				withCredentials: true,
+				reportProgress: true
+			}
+		);
 
+		return this.httpClient.request( request );
+	}
+}
 ```
 
-Next, in your component, create a function that can be plugged into CKEditor that
-will generate an UploadAdapter as needed:
+This class will be instantiated each time that CKEditor needs it.  Note that
+the functions in this class will run outside an `NgZone` which means that
+if it makes changes to variables bound to HTML elements, the shadow-DOM logic
+in the Angular framework won't detect those changes.
 
-```ts
-  MyUploadAdapterPlugin(editor) {
-    editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
-      return new UploadAdapter(loader, '/image');  // MODIFY FOR YOUR SERVER
-    };
-  }
-```
+The instance property `loader` is the primary interface between the UploadAdapter
+and the CKEditor instance.
 
 The second parameter is the URL where the image will be sent.  This will need
 to have everything the `imageURL` function in the UploadAdpater needs to
@@ -455,27 +454,6 @@ using the `extraPlugins` element in the configuration object, which can
 be used without rebuilding the standard build you are using.  The following
 instance variable can be defined:
 
-```ts
-  ckconfig = {
-    extraPlugins: [ (ei) => this.MyUploadAdapterPlugin(ei) ]
-  };
-```
-
-Any other desired configuration settings can be added (such as `toolbar`).
-Then it can be used in the `<ckeditor>` component as follows:
-
-```html
-        <ckeditor [editor]="Editor" [config]="ckconfig"
-                  [(ngModel)]="text" name="editcontent"></ckeditor>
-```
-
-Note the use of a closure in the `extraPlugins` array in the configuration.
-This is done so that the `MyUploadAdapterPlugin` function will have access
-to the properties of the component instance that spawned it.
-
-At this point your UploadAdapter should be invoked any time the user pastes
-or drag-and-drops an image into the `<ckeditor>` window.
-
 ## Localization
 
 The CKEditor 5 component can be localized in two steps.