MOBILE-2333 siteaddons: Support creating new components
Now site addons can return a ComponentRef instead of the component class in the getComponent functions of the delegates. This means they can create a new component on the fly using CoreCompileProvider.instantiateDynamicComponentmain
parent
ffa5a53fc6
commit
d98088f6a6
|
@ -13,7 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Component, OnInit, OnDestroy, Input, Output, EventEmitter, Optional } from '@angular/core';
|
||||
import { NavParams, NavController, Content, PopoverController } from 'ionic-angular';
|
||||
import { Content, PopoverController } from 'ionic-angular';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { NavController, NavOptions } from 'ionic-angular';
|
||||
import { AddonModBookProvider } from './book';
|
||||
import { AddonModBookIndexComponent } from '../components/index/index';
|
||||
|
@ -60,12 +60,14 @@ export class AddonModBookModuleHandler implements CoreCourseModuleHandler {
|
|||
/**
|
||||
* Get the component to render the module. This is needed to support singleactivity course format.
|
||||
* The component returned must implement CoreCourseModuleMainComponent.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course object.
|
||||
* @param {any} module The module object.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getMainComponent(course: any, module: any): any {
|
||||
getMainComponent(injector: Injector, course: any, module: any): any | Promise<any> {
|
||||
return AddonModBookIndexComponent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@core/course/providers/module-delegate';
|
||||
|
||||
/**
|
||||
|
@ -58,12 +58,14 @@ export class AddonModLabelModuleHandler implements CoreCourseModuleHandler {
|
|||
/**
|
||||
* Get the component to render the module. This is needed to support singleactivity course format.
|
||||
* The component returned must implement CoreCourseModuleMainComponent.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course object.
|
||||
* @param {any} module The module object.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getMainComponent(course: any, module: any): any {
|
||||
getMainComponent(injector: Injector, course: any, module: any): any | Promise<any> {
|
||||
// There's no need to implement this because label cannot be used in singleactivity course format.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from
|
||||
'../../../../core/user/providers/user-profile-field-delegate';
|
||||
import { AddonUserProfileFieldCheckboxComponent } from '../component/checkbox';
|
||||
|
@ -60,10 +60,12 @@ export class AddonUserProfileFieldCheckboxHandler implements CoreUserProfileFiel
|
|||
|
||||
/**
|
||||
* Return the Component to use to display the user profile field.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @param {Injector} injector Injector.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getComponent(): any {
|
||||
getComponent(injector: Injector): any | Promise<any> {
|
||||
return AddonUserProfileFieldCheckboxComponent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from
|
||||
'../../../../core/user/providers/user-profile-field-delegate';
|
||||
import { AddonUserProfileFieldDatetimeComponent } from '../component/datetime';
|
||||
|
@ -62,10 +62,12 @@ export class AddonUserProfileFieldDatetimeHandler implements CoreUserProfileFiel
|
|||
|
||||
/**
|
||||
* Return the Component to use to display the user profile field.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @param {Injector} injector Injector.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getComponent(): any {
|
||||
getComponent(injector: Injector): any | Promise<any> {
|
||||
return AddonUserProfileFieldDatetimeComponent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from
|
||||
'../../../../core/user/providers/user-profile-field-delegate';
|
||||
import { AddonUserProfileFieldMenuComponent } from '../component/menu';
|
||||
|
@ -60,10 +60,12 @@ export class AddonUserProfileFieldMenuHandler implements CoreUserProfileFieldHan
|
|||
|
||||
/**
|
||||
* Return the Component to use to display the user profile field.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @param {Injector} injector Injector.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getComponent(): any {
|
||||
getComponent(injector: Injector): any | Promise<any> {
|
||||
return AddonUserProfileFieldMenuComponent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from
|
||||
'../../../../core/user/providers/user-profile-field-delegate';
|
||||
import { AddonUserProfileFieldTextComponent } from '../component/text';
|
||||
|
@ -57,10 +57,12 @@ export class AddonUserProfileFieldTextHandler implements CoreUserProfileFieldHan
|
|||
|
||||
/**
|
||||
* Return the Component to use to display the user profile field.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @param {Injector} injector Injector.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getComponent(): any {
|
||||
getComponent(injector: Injector): any | Promise<any> {
|
||||
return AddonUserProfileFieldTextComponent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from
|
||||
'../../../../core/user/providers/user-profile-field-delegate';
|
||||
import { AddonUserProfileFieldTextareaComponent } from '../component/textarea';
|
||||
|
@ -66,10 +66,12 @@ export class AddonUserProfileFieldTextareaHandler implements CoreUserProfileFiel
|
|||
|
||||
/**
|
||||
* Return the Component to use to display the user profile field.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @param {Injector} injector Injector.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getComponent(): any {
|
||||
getComponent(injector: Injector): any | Promise<any> {
|
||||
return AddonUserProfileFieldTextareaComponent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,10 @@
|
|||
// limitations under the License.
|
||||
|
||||
import {
|
||||
Component, Input, ViewChild, OnInit, OnChanges, DoCheck, ViewContainerRef, ComponentFactoryResolver,
|
||||
KeyValueDiffers, SimpleChange
|
||||
Component, Input, ViewChild, OnInit, OnChanges, DoCheck, ViewContainerRef, ComponentFactoryResolver, ComponentRef,
|
||||
KeyValueDiffers, SimpleChange, ChangeDetectorRef, Optional, ElementRef
|
||||
} from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
|
||||
/**
|
||||
|
@ -39,6 +40,10 @@ import { CoreLoggerProvider } from '@providers/logger';
|
|||
*
|
||||
* Please notice that the component that you pass needs to be declared in entryComponents of the module to be created dynamically.
|
||||
*
|
||||
* Alternatively, you can also supply a ComponentRef instead of the class of the component. In this case, the component won't
|
||||
* be instantiated because it already is, it will be attached to the view and the right data will be passed to it.
|
||||
* Passing ComponentRef is meant for site addons, so we'll inject a NavController instance to the component.
|
||||
*
|
||||
* The contents of this component will be displayed if no component is supplied or it cannot be created. In the example above,
|
||||
* if no component is supplied then the template will show the message "Cannot render the data.".
|
||||
*/
|
||||
|
@ -62,7 +67,8 @@ export class CoreDynamicComponent implements OnInit, OnChanges, DoCheck {
|
|||
protected logger: any;
|
||||
protected differ: any; // To detect changes in the data input.
|
||||
|
||||
constructor(logger: CoreLoggerProvider, private factoryResolver: ComponentFactoryResolver, differs: KeyValueDiffers) {
|
||||
constructor(logger: CoreLoggerProvider, protected factoryResolver: ComponentFactoryResolver, differs: KeyValueDiffers,
|
||||
@Optional() protected navCtrl: NavController, protected cdr: ChangeDetectorRef, protected element: ElementRef) {
|
||||
this.logger = logger.getInstance('CoreDynamicComponent');
|
||||
this.differ = differs.find([]).create();
|
||||
}
|
||||
|
@ -128,21 +134,32 @@ export class CoreDynamicComponent implements OnInit, OnChanges, DoCheck {
|
|||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
// Create the component and add it to the container.
|
||||
const factory = this.factoryResolver.resolveComponentFactory(this.component),
|
||||
componentRef = this.container.createComponent(factory);
|
||||
if (this.component instanceof ComponentRef) {
|
||||
// A ComponentRef was supplied instead of the component class. Add it to the view.
|
||||
this.container.insert(this.component.hostView);
|
||||
this.instance = this.component.instance;
|
||||
|
||||
this.instance = componentRef.instance;
|
||||
// This feature is usually meant for site addons. Inject some properties.
|
||||
this.instance['ChangeDetectorRef'] = this.cdr;
|
||||
this.instance['NavController'] = this.navCtrl;
|
||||
this.instance['componentContainer'] = this.element.nativeElement;
|
||||
} else {
|
||||
try {
|
||||
// Create the component and add it to the container.
|
||||
const factory = this.factoryResolver.resolveComponentFactory(this.component),
|
||||
componentRef = this.container.createComponent(factory);
|
||||
|
||||
this.setInputData();
|
||||
this.instance = componentRef.instance;
|
||||
} catch (ex) {
|
||||
this.logger.error('Error creating component', ex);
|
||||
|
||||
return true;
|
||||
} catch (ex) {
|
||||
this.logger.error('Error creating component', ex);
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this.setInputData();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
// Code based on https://github.com/martinpritchardelevate/ionic-split-pane-demo
|
||||
|
||||
import { Component, ViewChild, Input, ElementRef, OnInit } from '@angular/core';
|
||||
import { Component, ViewChild, Input, ElementRef, OnInit, Optional } from '@angular/core';
|
||||
import { NavController, Nav } from 'ionic-angular';
|
||||
|
||||
/**
|
||||
|
@ -54,7 +54,7 @@ export class CoreSplitViewComponent implements OnInit {
|
|||
// Empty placeholder for the 'detail' page.
|
||||
detailPage: any = null;
|
||||
|
||||
constructor(private masterNav: NavController, element: ElementRef) {
|
||||
constructor(@Optional() private masterNav: NavController, element: ElementRef) {
|
||||
this.element = element.nativeElement;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,24 +13,12 @@
|
|||
// limitations under the License.
|
||||
|
||||
import {
|
||||
Component, NgModule, Input, OnInit, OnChanges, OnDestroy, ViewContainerRef, Compiler, ViewChild, ComponentRef,
|
||||
SimpleChange, ChangeDetectorRef
|
||||
Component, Input, OnInit, OnChanges, OnDestroy, ViewContainerRef, ViewChild, ComponentRef, SimpleChange, ChangeDetectorRef,
|
||||
ElementRef, Optional
|
||||
} from '@angular/core';
|
||||
import { IonicModule, NavController } from 'ionic-angular';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreCompileProvider } from '../../../compile/providers/compile';
|
||||
|
||||
// Import all modules that define components, directives and pipes.
|
||||
import { CoreComponentsModule } from '../../../../components/components.module';
|
||||
import { CoreDirectivesModule } from '../../../../directives/directives.module';
|
||||
import { CorePipesModule } from '../../../../pipes/pipes.module';
|
||||
import { CoreCourseComponentsModule } from '../../../course/components/components.module';
|
||||
import { CoreCourseDirectivesModule } from '../../../course/directives/directives.module';
|
||||
import { CoreCoursesComponentsModule } from '../../../courses/components/components.module';
|
||||
import { CoreSiteAddonsDirectivesModule } from '../../../siteaddons/directives/directives.module';
|
||||
import { CoreSiteHomeComponentsModule } from '../../../sitehome/components/components.module';
|
||||
import { CoreUserComponentsModule } from '../../../user/components/components.module';
|
||||
|
||||
/**
|
||||
* This component has a behaviour similar to $compile for AngularJS. Given an HTML code, it will compile it so all its
|
||||
* components and directives are instantiated.
|
||||
|
@ -51,13 +39,6 @@ import { CoreUserComponentsModule } from '../../../user/components/components.mo
|
|||
template: '<ng-container #dynamicComponent></ng-container>'
|
||||
})
|
||||
export class CoreCompileHtmlComponent implements OnChanges, OnDestroy {
|
||||
// List of imports for dynamic module. Since the template can have any component we need to import all core components modules.
|
||||
protected IMPORTS = [
|
||||
IonicModule, TranslateModule.forChild(), CoreComponentsModule, CoreDirectivesModule, CorePipesModule,
|
||||
CoreCourseComponentsModule, CoreCoursesComponentsModule, CoreSiteHomeComponentsModule, CoreUserComponentsModule,
|
||||
CoreCourseDirectivesModule, CoreSiteAddonsDirectivesModule
|
||||
];
|
||||
|
||||
@Input() text: string; // The HTML text to display.
|
||||
@Input() javascript: string; // The Javascript to execute in the component.
|
||||
@Input() jsData; // Data to pass to the fake component.
|
||||
|
@ -66,9 +47,12 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy {
|
|||
@ViewChild('dynamicComponent', { read: ViewContainerRef }) container: ViewContainerRef;
|
||||
|
||||
protected componentRef: ComponentRef<any>;
|
||||
protected element;
|
||||
|
||||
constructor(protected compileProvider: CoreCompileProvider, protected compiler: Compiler,
|
||||
protected cdr: ChangeDetectorRef, protected navCtrl: NavController) { }
|
||||
constructor(protected compileProvider: CoreCompileProvider, protected cdr: ChangeDetectorRef, element: ElementRef,
|
||||
@Optional() protected navCtrl: NavController) {
|
||||
this.element = element.nativeElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect changes on input properties.
|
||||
|
@ -76,26 +60,14 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy {
|
|||
ngOnChanges(changes: { [name: string]: SimpleChange }): void {
|
||||
if ((changes.text || changes.javascript) && this.text) {
|
||||
// Create a new component and a new module.
|
||||
const component = this.createComponent(),
|
||||
module = NgModule({imports: this.IMPORTS, declarations: [component]})(class {});
|
||||
|
||||
// Compile the module and the component.
|
||||
this.compiler.compileModuleAndAllComponentsAsync(module).then((factories) => {
|
||||
// Search the factory of the component we just created.
|
||||
let componentFactory;
|
||||
for (const i in factories.componentFactories) {
|
||||
const factory = factories.componentFactories[i];
|
||||
if (factory.componentType == component) {
|
||||
componentFactory = factory;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.compileProvider.createAndCompileComponent(this.text, this.getComponentClass()).then((factory) => {
|
||||
// Destroy previous components.
|
||||
this.componentRef && this.componentRef.destroy();
|
||||
|
||||
// Create the component.
|
||||
this.componentRef = this.container.createComponent(componentFactory);
|
||||
if (factory) {
|
||||
// Create the component.
|
||||
this.componentRef = this.container.createComponent(factory);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -108,20 +80,16 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a dynamic component to compile the HTML and run the javascript.
|
||||
* Get a class that defines the dynamic component.
|
||||
*
|
||||
* @return {any} The component class.
|
||||
*/
|
||||
protected createComponent(): any {
|
||||
protected getComponentClass(): any {
|
||||
// tslint:disable: no-this-assignment
|
||||
const compileInstance = this;
|
||||
|
||||
// Create the component, using the text as the template.
|
||||
return Component({
|
||||
template: this.text
|
||||
})
|
||||
(class CoreCompileHtmlFakeComponent implements OnInit {
|
||||
|
||||
return class CoreCompileHtmlFakeComponent implements OnInit {
|
||||
constructor() {
|
||||
// If there is some javascript to run, prepare the instance.
|
||||
if (compileInstance.javascript) {
|
||||
|
@ -130,7 +98,7 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy {
|
|||
// Add some more components and classes.
|
||||
this['ChangeDetectorRef'] = compileInstance.cdr;
|
||||
this['NavController'] = compileInstance.navCtrl;
|
||||
this['componentContainer'] = compileInstance.container;
|
||||
this['componentContainer'] = compileInstance.element;
|
||||
|
||||
// Add the data passed to the component.
|
||||
for (const name in compileInstance.jsData) {
|
||||
|
@ -145,6 +113,6 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy {
|
|||
compileInstance.compileProvider.executeJavascript(this, compileInstance.javascript);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,11 +12,12 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { Injectable, Injector, Component, NgModule, Compiler, ComponentFactory, ComponentRef, NgModuleRef } from '@angular/core';
|
||||
import {
|
||||
Platform, ActionSheetController, AlertController, LoadingController, ModalController, PopoverController, ToastController
|
||||
Platform, ActionSheetController, AlertController, LoadingController, ModalController, PopoverController, ToastController,
|
||||
IonicModule
|
||||
} from 'ionic-angular';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { TranslateService, TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreLoggerProvider } from '../../../providers/logger';
|
||||
|
||||
// Import core providers.
|
||||
|
@ -55,6 +56,24 @@ import { CoreContentLinksModuleGradeHandler } from '../../contentlinks/classes/m
|
|||
import { CoreContentLinksModuleIndexHandler } from '../../contentlinks/classes/module-index-handler';
|
||||
import { CoreCourseModulePrefetchHandlerBase } from '../../course/classes/module-prefetch-handler';
|
||||
|
||||
// Import all modules that define components, directives and pipes.
|
||||
import { CoreComponentsModule } from '../../../components/components.module';
|
||||
import { CoreDirectivesModule } from '../../../directives/directives.module';
|
||||
import { CorePipesModule } from '../../../pipes/pipes.module';
|
||||
import { CoreCourseComponentsModule } from '../../course/components/components.module';
|
||||
import { CoreCourseDirectivesModule } from '../../course/directives/directives.module';
|
||||
import { CoreCoursesComponentsModule } from '../../courses/components/components.module';
|
||||
import { CoreSiteAddonsDirectivesModule } from '../../siteaddons/directives/directives.module';
|
||||
import { CoreSiteHomeComponentsModule } from '../../sitehome/components/components.module';
|
||||
import { CoreUserComponentsModule } from '../../user/components/components.module';
|
||||
|
||||
// Import some components listed in entryComponents so they can be injected dynamically.
|
||||
import { CoreCourseUnsupportedModuleComponent } from '../../course/components/unsupported-module/unsupported-module';
|
||||
import { CoreCourseFormatSingleActivityComponent } from '../../course/formats/singleactivity/components/singleactivity';
|
||||
import { CoreSiteAddonsModuleIndexComponent } from '../../siteaddons/components/module-index/module-index';
|
||||
import { CoreSiteAddonsCourseOptionComponent } from '../../siteaddons/components/course-option/course-option';
|
||||
import { CoreSiteAddonsCourseFormatComponent } from '../../siteaddons/components/course-format/course-format';
|
||||
|
||||
/**
|
||||
* Service to provide functionalities regarding compiling dynamic HTML and Javascript.
|
||||
*/
|
||||
|
@ -69,10 +88,46 @@ export class CoreCompileProvider {
|
|||
ModalController, PopoverController, ToastController, FormBuilder
|
||||
];
|
||||
|
||||
constructor(protected injector: Injector, logger: CoreLoggerProvider) {
|
||||
// List of imports for dynamic module. Since the template can have any component we need to import all core components modules.
|
||||
protected IMPORTS = [
|
||||
IonicModule, TranslateModule.forChild(), CoreComponentsModule, CoreDirectivesModule, CorePipesModule,
|
||||
CoreCourseComponentsModule, CoreCoursesComponentsModule, CoreSiteHomeComponentsModule, CoreUserComponentsModule,
|
||||
CoreCourseDirectivesModule, CoreSiteAddonsDirectivesModule
|
||||
];
|
||||
|
||||
constructor(protected injector: Injector, logger: CoreLoggerProvider, protected compiler: Compiler) {
|
||||
this.logger = logger.getInstance('CoreCompileProvider');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and compile a dynamic component.
|
||||
*
|
||||
* @param {string} template The template of the component.
|
||||
* @param {any} componentClass The JS class of the component.
|
||||
* @return {Promise<ComponentFactory<any>>} Promise resolved with the factory to instantiate the component.
|
||||
*/
|
||||
createAndCompileComponent(template: string, componentClass: any): Promise<ComponentFactory<any>> {
|
||||
// Create the component using the template and the class.
|
||||
const component = Component({
|
||||
template: template
|
||||
})
|
||||
(componentClass);
|
||||
|
||||
// Now create the module containing the component.
|
||||
const module = NgModule({imports: this.IMPORTS, declarations: [component]})(class {});
|
||||
|
||||
// Compile the module and the component.
|
||||
return this.compiler.compileModuleAndAllComponentsAsync(module).then((factories) => {
|
||||
// Search and return the factory of the component we just created.
|
||||
for (const i in factories.componentFactories) {
|
||||
const factory = factories.componentFactories[i];
|
||||
if (factory.componentType == component) {
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Eval some javascript using the context of the function.
|
||||
*
|
||||
|
@ -124,6 +179,9 @@ export class CoreCompileProvider {
|
|||
}
|
||||
}
|
||||
|
||||
// Inject current service.
|
||||
instance['CoreCompileProvider'] = this;
|
||||
|
||||
// Add some final classes.
|
||||
instance['injector'] = this.injector;
|
||||
instance['Validators'] = Validators;
|
||||
|
@ -138,5 +196,29 @@ export class CoreCompileProvider {
|
|||
instance['CoreContentLinksModuleGradeHandler'] = CoreContentLinksModuleGradeHandler;
|
||||
instance['CoreContentLinksModuleIndexHandler'] = CoreContentLinksModuleIndexHandler;
|
||||
instance['CoreCourseModulePrefetchHandlerBase'] = CoreCourseModulePrefetchHandlerBase;
|
||||
instance['CoreCourseUnsupportedModuleComponent'] = CoreCourseUnsupportedModuleComponent;
|
||||
instance['CoreCourseFormatSingleActivityComponent'] = CoreCourseFormatSingleActivityComponent;
|
||||
instance['CoreSiteAddonsModuleIndexComponent'] = CoreSiteAddonsModuleIndexComponent;
|
||||
instance['CoreSiteAddonsCourseOptionComponent'] = CoreSiteAddonsCourseOptionComponent;
|
||||
instance['CoreSiteAddonsCourseFormatComponent'] = CoreSiteAddonsCourseFormatComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a dynamic component.
|
||||
*
|
||||
* @param {string} template The template of the component.
|
||||
* @param {any} componentClass The JS class of the component.
|
||||
* @param {Injector} [injector] The injector to use. It's recommended to pass it so NavController and similar can be injected.
|
||||
* @return {Promise<ComponentRef<any>>} Promise resolved with the component instance.
|
||||
*/
|
||||
instantiateDynamicComponent(template: string, componentClass: any, injector?: Injector): Promise<ComponentRef<any>> {
|
||||
injector = injector || this.injector;
|
||||
|
||||
return this.createAndCompileComponent(template, componentClass).then((factory) => {
|
||||
if (factory) {
|
||||
// Create and return the component.
|
||||
return factory.create(injector, undefined, undefined, injector.get(NgModuleRef));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
import {
|
||||
Component, Input, OnInit, OnChanges, OnDestroy, SimpleChange, Output, EventEmitter, ViewChildren, QueryList
|
||||
Component, Input, OnInit, OnChanges, OnDestroy, SimpleChange, Output, EventEmitter, ViewChildren, QueryList, Injector
|
||||
} from '@angular/core';
|
||||
import { Content } from 'ionic-angular';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
@ -69,7 +69,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
|||
|
||||
protected sectionStatusObserver;
|
||||
|
||||
constructor(private cfDelegate: CoreCourseFormatDelegate, translate: TranslateService,
|
||||
constructor(private cfDelegate: CoreCourseFormatDelegate, translate: TranslateService, private injector: Injector,
|
||||
private courseHelper: CoreCourseHelperProvider, private domUtils: CoreDomUtilsProvider,
|
||||
eventsProvider: CoreEventsProvider, private sitesProvider: CoreSitesProvider, private content: Content,
|
||||
prefetchDelegate: CoreCourseModulePrefetchDelegate) {
|
||||
|
@ -194,19 +194,29 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
|||
protected getComponents(): void {
|
||||
if (this.course) {
|
||||
if (!this.courseFormatComponent) {
|
||||
this.courseFormatComponent = this.cfDelegate.getCourseFormatComponent(this.course);
|
||||
this.cfDelegate.getCourseFormatComponent(this.injector, this.course).then((component) => {
|
||||
this.courseFormatComponent = component;
|
||||
});
|
||||
}
|
||||
if (!this.courseSummaryComponent) {
|
||||
this.courseSummaryComponent = this.cfDelegate.getCourseSummaryComponent(this.course);
|
||||
this.cfDelegate.getCourseSummaryComponent(this.injector, this.course).then((component) => {
|
||||
this.courseSummaryComponent = component;
|
||||
});
|
||||
}
|
||||
if (!this.sectionSelectorComponent) {
|
||||
this.sectionSelectorComponent = this.cfDelegate.getSectionSelectorComponent(this.course);
|
||||
this.cfDelegate.getSectionSelectorComponent(this.injector, this.course).then((component) => {
|
||||
this.sectionSelectorComponent = component;
|
||||
});
|
||||
}
|
||||
if (!this.singleSectionComponent) {
|
||||
this.singleSectionComponent = this.cfDelegate.getSingleSectionComponent(this.course);
|
||||
this.cfDelegate.getSingleSectionComponent(this.injector, this.course).then((component) => {
|
||||
this.singleSectionComponent = component;
|
||||
});
|
||||
}
|
||||
if (!this.allSectionsComponent) {
|
||||
this.allSectionsComponent = this.cfDelegate.getAllSectionsComponent(this.course);
|
||||
this.cfDelegate.getAllSectionsComponent(this.injector, this.course).then((component) => {
|
||||
this.allSectionsComponent = component;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, Input, Output, EventEmitter, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, Optional } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
|
@ -67,7 +67,7 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
|||
protected prefetchHandler: CoreCourseModulePrefetchHandler;
|
||||
protected statusObserver;
|
||||
|
||||
constructor(protected navCtrl: NavController, protected prefetchDelegate: CoreCourseModulePrefetchDelegate,
|
||||
constructor(@Optional() protected navCtrl: NavController, protected prefetchDelegate: CoreCourseModulePrefetchDelegate,
|
||||
protected domUtils: CoreDomUtilsProvider, protected courseHelper: CoreCourseHelperProvider,
|
||||
protected eventsProvider: CoreEventsProvider, protected sitesProvider: CoreSitesProvider) {
|
||||
this.completionChanged = new EventEmitter();
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, Input, OnChanges, SimpleChange, ViewChild } from '@angular/core';
|
||||
import { Component, Input, OnChanges, SimpleChange, ViewChild, Injector } from '@angular/core';
|
||||
import { CoreCourseModuleDelegate } from '../../../providers/module-delegate';
|
||||
import { CoreCourseUnsupportedModuleComponent } from '../../../components/unsupported-module/unsupported-module';
|
||||
import { CoreDynamicComponent } from '../../../../../components/dynamic-component/dynamic-component';
|
||||
|
@ -36,7 +36,7 @@ export class CoreCourseFormatSingleActivityComponent implements OnChanges {
|
|||
componentClass: any; // The class of the component to render.
|
||||
data: any = {}; // Data to pass to the component.
|
||||
|
||||
constructor(private moduleDelegate: CoreCourseModuleDelegate) { }
|
||||
constructor(private moduleDelegate: CoreCourseModuleDelegate, private injector: Injector) { }
|
||||
|
||||
/**
|
||||
* Detect changes on input properties.
|
||||
|
@ -47,8 +47,9 @@ export class CoreCourseFormatSingleActivityComponent implements OnChanges {
|
|||
const module = this.sections[0] && this.sections[0].modules && this.sections[0].modules[0];
|
||||
if (module && !this.componentClass) {
|
||||
// We haven't obtained the class yet. Get it now.
|
||||
this.componentClass = this.moduleDelegate.getMainComponent(this.course, module) ||
|
||||
CoreCourseUnsupportedModuleComponent;
|
||||
this.moduleDelegate.getMainComponent(this.injector, this.course, module).then((component) => {
|
||||
this.componentClass = component || CoreCourseUnsupportedModuleComponent;
|
||||
});
|
||||
}
|
||||
|
||||
this.data.courseId = this.course.id;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { CoreCourseFormatHandler } from '../../../providers/format-delegate';
|
||||
import { CoreCourseFormatSingleActivityComponent } from '../components/singleactivity';
|
||||
|
||||
|
@ -86,11 +86,13 @@ export class CoreCourseFormatSingleActivityHandler implements CoreCourseFormatHa
|
|||
* Return the Component to use to display the course format instead of using the default one.
|
||||
* Use it if you want to display a format completely different from the default one.
|
||||
* If you want to customize the default format there are several methods to customize parts of it.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getCourseFormatComponent(course: any): any {
|
||||
getCourseFormatComponent(injector: Injector, course: any): any | Promise<any> {
|
||||
return CoreCourseFormatSingleActivityComponent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, ViewChild, OnDestroy } from '@angular/core';
|
||||
import { Component, ViewChild, OnDestroy, Injector } from '@angular/core';
|
||||
import { IonicPage, NavParams, Content, NavController } from 'ionic-angular';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
|
@ -63,7 +63,7 @@ export class CoreCourseSectionPage implements OnDestroy {
|
|||
private courseFormatDelegate: CoreCourseFormatDelegate, private courseOptionsDelegate: CoreCourseOptionsDelegate,
|
||||
private translate: TranslateService, private courseHelper: CoreCourseHelperProvider, eventsProvider: CoreEventsProvider,
|
||||
private textUtils: CoreTextUtilsProvider, private coursesProvider: CoreCoursesProvider,
|
||||
sitesProvider: CoreSitesProvider, private navCtrl: NavController,
|
||||
sitesProvider: CoreSitesProvider, private navCtrl: NavController, private injector: Injector,
|
||||
private prefetchDelegate: CoreCourseModulePrefetchDelegate) {
|
||||
this.course = navParams.get('course');
|
||||
this.sectionId = navParams.get('sectionId');
|
||||
|
@ -191,7 +191,8 @@ export class CoreCourseSectionPage implements OnDestroy {
|
|||
}));
|
||||
|
||||
// Load the course handlers.
|
||||
promises.push(this.courseOptionsDelegate.getHandlersToDisplay(this.course, refresh, false).then((handlers) => {
|
||||
promises.push(this.courseOptionsDelegate.getHandlersToDisplay(this.injector, this.course, refresh, false)
|
||||
.then((handlers) => {
|
||||
// Add the courseId to the handler component data.
|
||||
handlers.forEach((handler) => {
|
||||
handler.data.componentData = handler.data.componentData || {};
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
|
@ -85,44 +85,54 @@ export interface CoreCourseFormatHandler extends CoreDelegateHandler {
|
|||
* Return the Component to use to display the course format instead of using the default one.
|
||||
* Use it if you want to display a format completely different from the default one.
|
||||
* If you want to customize the default format there are several methods to customize parts of it.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getCourseFormatComponent?(course: any): any;
|
||||
getCourseFormatComponent?(injector: Injector, course: any): any | Promise<any>;
|
||||
|
||||
/**
|
||||
* Return the Component to use to display the course summary inside the default course format.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getCourseSummaryComponent?(course: any): any;
|
||||
getCourseSummaryComponent?(injector: Injector, course: any): any | Promise<any>;
|
||||
|
||||
/**
|
||||
* Return the Component to use to display the section selector inside the default course format.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getSectionSelectorComponent?(course: any): any;
|
||||
getSectionSelectorComponent?(injector: Injector, course: any): any | Promise<any>;
|
||||
|
||||
/**
|
||||
* Return the Component to use to display a single section. This component will only be used if the user is viewing a
|
||||
* single section. If all the sections are displayed at once then it won't be used.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getSingleSectionComponent?(course: any): any;
|
||||
getSingleSectionComponent?(injector: Injector, course: any): any | Promise<any>;
|
||||
|
||||
/**
|
||||
* Return the Component to use to display all sections in a course.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getAllSectionsComponent?(course: any): any;
|
||||
getAllSectionsComponent?(injector: Injector, course: any): any | Promise<any>;
|
||||
|
||||
/**
|
||||
* Invalidate the data required to load the course format.
|
||||
|
@ -199,31 +209,40 @@ export class CoreCourseFormatDelegate extends CoreDelegate {
|
|||
/**
|
||||
* Get the component to use to display all sections in a course.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {Promise<any>} Promise resolved with component to use, undefined if not found.
|
||||
*/
|
||||
getAllSectionsComponent(course: any): any {
|
||||
return this.executeFunction(course.format, 'getAllSectionsComponent', [course]);
|
||||
getAllSectionsComponent(injector: Injector, course: any): Promise<any> {
|
||||
return Promise.resolve(this.executeFunction(course.format, 'getAllSectionsComponent', [injector, course])).catch((e) => {
|
||||
this.logger.error('Error getting all sections component', e);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the component to use to display a course format.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {Promise<any>} Promise resolved with component to use, undefined if not found.
|
||||
*/
|
||||
getCourseFormatComponent(course: any): any {
|
||||
return this.executeFunction(course.format, 'getCourseFormatComponent', [course]);
|
||||
getCourseFormatComponent(injector: Injector, course: any): Promise<any> {
|
||||
return Promise.resolve(this.executeFunction(course.format, 'getCourseFormatComponent', [injector, course])).catch((e) => {
|
||||
this.logger.error('Error getting course format component', e);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the component to use to display the course summary in the default course format.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {Promise<any>} Promise resolved with component to use, undefined if not found.
|
||||
*/
|
||||
getCourseSummaryComponent(course: any): any {
|
||||
return this.executeFunction(course.format, 'getCourseSummaryComponent', [course]);
|
||||
getCourseSummaryComponent(injector: Injector, course: any): Promise<any> {
|
||||
return Promise.resolve(this.executeFunction(course.format, 'getCourseSummaryComponent', [injector, course])).catch((e) => {
|
||||
this.logger.error('Error getting course summary component', e);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -259,22 +278,29 @@ export class CoreCourseFormatDelegate extends CoreDelegate {
|
|||
/**
|
||||
* Get the component to use to display the section selector inside the default course format.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {Promise<any>} Promise resolved with component to use, undefined if not found.
|
||||
*/
|
||||
getSectionSelectorComponent(course: any): any {
|
||||
return this.executeFunction(course.format, 'getSectionSelectorComponent', [course]);
|
||||
getSectionSelectorComponent(injector: Injector, course: any): Promise<any> {
|
||||
return Promise.resolve(this.executeFunction(course.format, 'getSectionSelectorComponent', [injector, course]))
|
||||
.catch((e) => {
|
||||
this.logger.error('Error getting section selector component', e);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the component to use to display a single section. This component will only be used if the user is viewing
|
||||
* a single section. If all the sections are displayed at once then it won't be used.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {Promise<any>} Promise resolved with component to use, undefined if not found.
|
||||
*/
|
||||
getSingleSectionComponent(course: any): any {
|
||||
return this.executeFunction(course.format, 'getSingleSectionComponent', [course]);
|
||||
getSingleSectionComponent(injector: Injector, course: any): Promise<any> {
|
||||
return Promise.resolve(this.executeFunction(course.format, 'getSingleSectionComponent', [injector, course])).catch((e) => {
|
||||
this.logger.error('Error getting single section component', e);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
|
@ -120,7 +120,7 @@ export class CoreCourseHelperProvider {
|
|||
private utils: CoreUtilsProvider, private translate: TranslateService, private loginHelper: CoreLoginHelperProvider,
|
||||
private courseOptionsDelegate: CoreCourseOptionsDelegate, private siteHomeProvider: CoreSiteHomeProvider,
|
||||
private eventsProvider: CoreEventsProvider, private fileHelper: CoreFileHelperProvider,
|
||||
private appProvider: CoreAppProvider, private fileProvider: CoreFileProvider) { }
|
||||
private appProvider: CoreAppProvider, private fileProvider: CoreFileProvider, private injector: Injector) { }
|
||||
|
||||
/**
|
||||
* This function treats every module on the sections provided to load the handler data, treat completion
|
||||
|
@ -275,7 +275,7 @@ export class CoreCourseHelperProvider {
|
|||
if (courseHandlers) {
|
||||
promise = Promise.resolve(courseHandlers);
|
||||
} else {
|
||||
promise = this.courseOptionsDelegate.getHandlersToDisplay(course);
|
||||
promise = this.courseOptionsDelegate.getHandlersToDisplay(this.injector, course);
|
||||
}
|
||||
|
||||
return promise.then((handlers: CoreCourseOptionsHandlerToDisplay[]) => {
|
||||
|
@ -323,7 +323,7 @@ export class CoreCourseHelperProvider {
|
|||
subPromises.push(this.courseProvider.getSections(course.id, false, true).then((courseSections) => {
|
||||
sections = courseSections;
|
||||
}));
|
||||
subPromises.push(this.courseOptionsDelegate.getHandlersToDisplay(course).then((cHandlers) => {
|
||||
subPromises.push(this.courseOptionsDelegate.getHandlersToDisplay(this.injector, course).then((cHandlers) => {
|
||||
handlers = cHandlers;
|
||||
}));
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { NavController, NavOptions } from 'ionic-angular';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
|
@ -38,12 +38,14 @@ export interface CoreCourseModuleHandler extends CoreDelegateHandler {
|
|||
/**
|
||||
* Get the component to render the module. This is needed to support singleactivity course format.
|
||||
* The component returned must implement CoreCourseModuleMainComponent.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course object.
|
||||
* @param {any} module The module object.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getMainComponent(course: any, module: any): any;
|
||||
getMainComponent(injector: Injector, course: any, module: any): any | Promise<any>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -176,17 +178,17 @@ export class CoreCourseModuleDelegate extends CoreDelegate {
|
|||
/**
|
||||
* Get the component to render the module.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course object.
|
||||
* @param {any} module The module object.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {Promise<any>} Promise resolved with component to use, undefined if not found.
|
||||
*/
|
||||
getMainComponent?(course: any, module: any): any {
|
||||
getMainComponent(injector: Injector, course: any, module: any): Promise<any> {
|
||||
const handler = this.enabledHandlers[module.modname];
|
||||
if (handler && handler.getMainComponent) {
|
||||
const component = handler.getMainComponent(course, module);
|
||||
if (component) {
|
||||
return component;
|
||||
}
|
||||
return Promise.resolve(handler.getMainComponent(injector, course, module)).catch((err) => {
|
||||
this.logger.error('Error getting main component', err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
|
@ -45,10 +45,11 @@ export interface CoreCourseOptionsHandler extends CoreDelegateHandler {
|
|||
/**
|
||||
* Returns the data needed to render the handler.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {number} courseId The course ID.
|
||||
* @return {CoreCourseOptionsHandlerData} Data.
|
||||
* @return {CoreCourseOptionsHandlerData|Promise<CoreCourseOptionsHandlerData>} Data or promise resolved with the data.
|
||||
*/
|
||||
getDisplayData?(courseId: number): CoreCourseOptionsHandlerData;
|
||||
getDisplayData?(injector: Injector, courseId: number): CoreCourseOptionsHandlerData | Promise<CoreCourseOptionsHandlerData>;
|
||||
|
||||
/**
|
||||
* Should invalidate the data to determine if the handler is enabled for a certain course.
|
||||
|
@ -243,6 +244,7 @@ export class CoreCourseOptionsDelegate extends CoreDelegate {
|
|||
* Get the list of handlers that should be displayed for a course.
|
||||
* This function should be called only when the handlers need to be displayed, since it can call several WebServices.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course object.
|
||||
* @param {boolean} [refresh] True if it should refresh the list.
|
||||
* @param {boolean} [isGuest] Whether it's guest.
|
||||
|
@ -250,7 +252,7 @@ export class CoreCourseOptionsDelegate extends CoreDelegate {
|
|||
* @param {any} [admOptions] Course admin options for current user. See CoreCoursesProvider.getUserAdministrationOptions.
|
||||
* @return {Promise<CoreCourseOptionsHandlerToDisplay[]>} Promise resolved with array of handlers.
|
||||
*/
|
||||
getHandlersToDisplay(course: any, refresh?: boolean, isGuest?: boolean, navOptions?: any, admOptions?: any):
|
||||
getHandlersToDisplay(injector: Injector, course: any, refresh?: boolean, isGuest?: boolean, navOptions?: any, admOptions?: any):
|
||||
Promise<CoreCourseOptionsHandlerToDisplay[]> {
|
||||
course.id = parseInt(course.id, 10);
|
||||
|
||||
|
@ -269,14 +271,19 @@ export class CoreCourseOptionsDelegate extends CoreDelegate {
|
|||
// Call getHandlersForAccess to make sure the handlers have been loaded.
|
||||
return this.getHandlersForAccess(course.id, refresh, accessData, course.navOptions, course.admOptions);
|
||||
}).then(() => {
|
||||
const handlersToDisplay: CoreCourseOptionsHandlerToDisplay[] = [];
|
||||
const handlersToDisplay: CoreCourseOptionsHandlerToDisplay[] = [],
|
||||
promises = [];
|
||||
|
||||
this.coursesHandlers[course.id].enabledHandlers.forEach((handler) => {
|
||||
handlersToDisplay.push({
|
||||
data: handler.getDisplayData(course),
|
||||
priority: handler.priority,
|
||||
prefetch: handler.prefetch
|
||||
});
|
||||
promises.push(Promise.resolve(handler.getDisplayData(injector, course)).then((data) => {
|
||||
handlersToDisplay.push({
|
||||
data: data,
|
||||
priority: handler.priority,
|
||||
prefetch: handler.prefetch
|
||||
});
|
||||
}).catch((err) => {
|
||||
this.logger.error('Error getting data for handler', handler.name, err);
|
||||
}));
|
||||
});
|
||||
|
||||
// Sort them by priority.
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { Component, Input, OnInit, Optional } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreCoursesProvider } from '../../providers/courses';
|
||||
|
@ -31,7 +31,8 @@ import { CoreCoursesProvider } from '../../providers/courses';
|
|||
export class CoreCoursesCourseListItemComponent implements OnInit {
|
||||
@Input() course: any; // The course to render.
|
||||
|
||||
constructor(private navCtrl: NavController, private translate: TranslateService, private coursesProvider: CoreCoursesProvider) {
|
||||
constructor(@Optional() private navCtrl: NavController, private translate: TranslateService,
|
||||
private coursesProvider: CoreCoursesProvider) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Component, Input, OnInit, OnDestroy, Optional } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
|
@ -44,7 +44,7 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
|
|||
protected isDestroyed = false;
|
||||
protected courseStatusObserver;
|
||||
|
||||
constructor(private navCtrl: NavController, private courseHelper: CoreCourseHelperProvider,
|
||||
constructor(@Optional() private navCtrl: NavController, private courseHelper: CoreCourseHelperProvider,
|
||||
private courseFormatDelegate: CoreCourseFormatDelegate, private domUtils: CoreDomUtilsProvider,
|
||||
private courseProvider: CoreCourseProvider, eventsProvider: CoreEventsProvider, sitesProvider: CoreSitesProvider) {
|
||||
// Listen for status change in course.
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, Input, Output, OnChanges, EventEmitter, SimpleChange } from '@angular/core';
|
||||
import { Component, Input, Output, OnChanges, EventEmitter, SimpleChange, Optional } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
|
@ -43,9 +43,10 @@ export class CoreCoursesOverviewEventsComponent implements OnChanges {
|
|||
next30Days: any[] = [];
|
||||
future: any[] = [];
|
||||
|
||||
constructor(private navCtrl: NavController, private utils: CoreUtilsProvider, private textUtils: CoreTextUtilsProvider,
|
||||
private domUtils: CoreDomUtilsProvider, private sitesProvider: CoreSitesProvider,
|
||||
private courseProvider: CoreCourseProvider, private contentLinksHelper: CoreContentLinksHelperProvider) {
|
||||
constructor(@Optional() private navCtrl: NavController, private utils: CoreUtilsProvider,
|
||||
private textUtils: CoreTextUtilsProvider, private domUtils: CoreDomUtilsProvider,
|
||||
private sitesProvider: CoreSitesProvider, private courseProvider: CoreCourseProvider,
|
||||
private contentLinksHelper: CoreContentLinksHelperProvider) {
|
||||
this.loadMore = new EventEmitter();
|
||||
}
|
||||
|
||||
|
|
|
@ -39,8 +39,9 @@ export class CoreGradesCourseComponent {
|
|||
gradesTable: any;
|
||||
|
||||
constructor(private gradesProvider: CoreGradesProvider, private domUtils: CoreDomUtilsProvider, navParams: NavParams,
|
||||
private gradesHelper: CoreGradesHelperProvider, private sitesProvider: CoreSitesProvider, private navCtrl: NavController,
|
||||
private appProvider: CoreAppProvider, @Optional() private svComponent: CoreSplitViewComponent) {
|
||||
private gradesHelper: CoreGradesHelperProvider, private sitesProvider: CoreSitesProvider,
|
||||
@Optional() private navCtrl: NavController, private appProvider: CoreAppProvider,
|
||||
@Optional() private svComponent: CoreSplitViewComponent) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreCourseOptionsHandler, CoreCourseOptionsHandlerData } from '../../course/providers/options-delegate';
|
||||
import { CoreCourseProvider } from '../../course/providers/course';
|
||||
|
@ -80,9 +80,11 @@ export class CoreGradesCourseOptionHandler implements CoreCourseOptionsHandler {
|
|||
/**
|
||||
* Returns the data needed to render the handler.
|
||||
*
|
||||
* @return {CoreCourseOptionsHandlerData} Data needed to render the handler.
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {number} courseId The course ID.
|
||||
* @return {CoreCourseOptionsHandlerData|Promise<CoreCourseOptionsHandlerData>} Data or promise resolved with the data.
|
||||
*/
|
||||
getDisplayData(): CoreCourseOptionsHandlerData {
|
||||
getDisplayData(injector: Injector, courseId: number): CoreCourseOptionsHandlerData | Promise<CoreCourseOptionsHandlerData> {
|
||||
return {
|
||||
title: 'core.grades.grades',
|
||||
class: 'core-grades-course-handler',
|
||||
|
|
|
@ -62,7 +62,7 @@ export class CoreSiteAddonsCallWSNewContentDirective extends CoreSiteAddonsCallW
|
|||
|
||||
constructor(element: ElementRef, translate: TranslateService, domUtils: CoreDomUtilsProvider,
|
||||
siteAddonsProvider: CoreSiteAddonsProvider, @Optional() parentContent: CoreSiteAddonsAddonContentComponent,
|
||||
protected utils: CoreUtilsProvider, protected navCtrl: NavController) {
|
||||
protected utils: CoreUtilsProvider, @Optional() protected navCtrl: NavController) {
|
||||
super(element, translate, domUtils, siteAddonsProvider, parentContent);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Directive, Input, OnInit, ElementRef, Optional } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreDomUtilsProvider } from '../../../providers/utils/dom';
|
||||
import { CoreUtilsProvider } from '../../../providers/utils/utils';
|
||||
|
|
|
@ -54,7 +54,7 @@ export class CoreSiteAddonsNewContentDirective implements OnInit {
|
|||
|
||||
protected element: HTMLElement;
|
||||
|
||||
constructor(element: ElementRef, protected utils: CoreUtilsProvider, protected navCtrl: NavController,
|
||||
constructor(element: ElementRef, protected utils: CoreUtilsProvider, @Optional() protected navCtrl: NavController,
|
||||
@Optional() protected parentContent: CoreSiteAddonsAddonContentComponent, protected domUtils: CoreDomUtilsProvider,
|
||||
protected siteAddonsProvider: CoreSiteAddonsProvider) {
|
||||
this.element = element.nativeElement || element;
|
||||
|
|
|
@ -43,6 +43,9 @@ import { CoreCoursesProvider } from '../../courses/providers/courses';
|
|||
* addons.
|
||||
*
|
||||
* This code is split from CoreSiteAddonsProvider to prevent circular dependencies.
|
||||
*
|
||||
* @todo: Support ViewChild and similar in site addons. Possible solution: make components and directives inject the instance
|
||||
* inside the host DOM element?
|
||||
*/
|
||||
@Injectable()
|
||||
export class CoreSiteAddonsHelperProvider {
|
||||
|
@ -337,7 +340,7 @@ export class CoreSiteAddonsHelperProvider {
|
|||
displaySectionSelector: (course: any): boolean => {
|
||||
return typeof handlerSchema.displaysectionselector != 'undefined' ? handlerSchema.displaysectionselector : true;
|
||||
},
|
||||
getCourseFormatComponent: (course: any): any => {
|
||||
getCourseFormatComponent: (injector: Injector, course: any): any | Promise<any> => {
|
||||
if (handlerSchema.method) {
|
||||
return CoreSiteAddonsCourseFormatComponent;
|
||||
}
|
||||
|
@ -377,7 +380,8 @@ export class CoreSiteAddonsHelperProvider {
|
|||
: boolean | Promise<boolean> => {
|
||||
return this.isHandlerEnabledForCourse(courseId, handlerSchema.restricttoenrolledcourses, bootstrapResult.restrict);
|
||||
},
|
||||
getDisplayData: (courseId: number): CoreCourseOptionsHandlerData => {
|
||||
getDisplayData: (injector: Injector, courseId: number):
|
||||
CoreCourseOptionsHandlerData | Promise<CoreCourseOptionsHandlerData> => {
|
||||
return {
|
||||
title: prefixedTitle,
|
||||
class: handlerSchema.displaydata.class,
|
||||
|
@ -488,7 +492,7 @@ export class CoreSiteAddonsHelperProvider {
|
|||
}
|
||||
};
|
||||
},
|
||||
getMainComponent: (course: any, module: any): any => {
|
||||
getMainComponent: (injector: Injector, course: any, module: any): any | Promise<any> => {
|
||||
return CoreSiteAddonsModuleIndexComponent;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -144,7 +144,10 @@ export class CoreSiteAddonsProvider {
|
|||
*/
|
||||
createDataForJS(bootstrapResult: any, contentResult?: any): any {
|
||||
// First of all, add the data returned by the bootstrap JS (if any).
|
||||
const data = this.utils.clone(bootstrapResult.jsResult || {});
|
||||
let data = this.utils.clone(bootstrapResult.jsResult || {});
|
||||
if (typeof data == 'boolean') {
|
||||
data = {};
|
||||
}
|
||||
|
||||
// Now add some data returned by the bootstrap WS call.
|
||||
data.BOOTSTRAP_TEMPLATES = this.utils.objectToKeyValueMap(bootstrapResult.templates, 'id', 'html');
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { Component, Input, OnInit, Injector } from '@angular/core';
|
||||
import { CoreUserProfileFieldDelegate } from '../../providers/user-profile-field-delegate';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
|
||||
|
@ -33,13 +33,16 @@ export class CoreUserProfileFieldComponent implements OnInit {
|
|||
componentClass: any; // The class of the component to render.
|
||||
data: any = {}; // Data to pass to the component.
|
||||
|
||||
constructor(private ufDelegate: CoreUserProfileFieldDelegate, private utilsProvider: CoreUtilsProvider) { }
|
||||
constructor(private ufDelegate: CoreUserProfileFieldDelegate, private utilsProvider: CoreUtilsProvider,
|
||||
private injector: Injector) { }
|
||||
|
||||
/**
|
||||
* Component being initialized.
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.componentClass = this.ufDelegate.getComponent(this.field, this.signup);
|
||||
this.ufDelegate.getComponent(this.injector, this.field, this.signup).then((component) => {
|
||||
this.componentClass = component;
|
||||
});
|
||||
|
||||
this.data.field = this.field;
|
||||
this.data.edit = this.utilsProvider.isTrueOrOne(this.edit);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreCourseOptionsHandler, CoreCourseOptionsHandlerData } from '../../course/providers/options-delegate';
|
||||
import { CoreCourseProvider } from '../../course/providers/course';
|
||||
|
@ -79,9 +79,11 @@ export class CoreUserParticipantsCourseOptionHandler implements CoreCourseOption
|
|||
/**
|
||||
* Returns the data needed to render the handler.
|
||||
*
|
||||
* @return {CoreCourseOptionsHandlerData} Data needed to render the handler.
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {number} courseId The course ID.
|
||||
* @return {CoreCourseOptionsHandlerData|Promise<CoreCourseOptionsHandlerData>} Data or promise resolved with the data.
|
||||
*/
|
||||
getDisplayData(): CoreCourseOptionsHandlerData {
|
||||
getDisplayData(injector: Injector, courseId: number): CoreCourseOptionsHandlerData | Promise<CoreCourseOptionsHandlerData> {
|
||||
return {
|
||||
title: 'core.user.participants',
|
||||
class: 'core-user-participants-handler',
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
|
@ -22,10 +22,12 @@ export interface CoreUserProfileFieldHandler extends CoreDelegateHandler {
|
|||
|
||||
/**
|
||||
* Return the Component to use to display the user profile field.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @param {Injector} injector Injector.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getComponent(): any;
|
||||
getComponent(injector: Injector): any | Promise<any>;
|
||||
|
||||
/**
|
||||
* Get the data to send for the field based on the input data.
|
||||
|
@ -75,17 +77,23 @@ export class CoreUserProfileFieldDelegate extends CoreDelegate {
|
|||
/**
|
||||
* Get the component to use to display an user field.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} field User field to get the directive for.
|
||||
* @param {boolean} signup True if user is in signup page.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {Promise<any>} Promise resolved with component to use, undefined if not found.
|
||||
*/
|
||||
getComponent(field: any, signup: boolean): any {
|
||||
getComponent(injector: Injector, field: any, signup: boolean): Promise<any> {
|
||||
const type = field.type || field.datatype;
|
||||
let result;
|
||||
if (signup) {
|
||||
return this.executeFunction(type, 'getComponent');
|
||||
result = this.executeFunction(type, 'getComponent', [injector]);
|
||||
} else {
|
||||
return this.executeFunctionOnEnabled(type, 'getComponent');
|
||||
result = this.executeFunctionOnEnabled(type, 'getComponent', [injector]);
|
||||
}
|
||||
|
||||
return Promise.resolve(result).catch((err) => {
|
||||
this.logger.error('Error getting component for field', type, err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Directive, Input, OnInit, ElementRef } from '@angular/core';
|
||||
import { Directive, Input, OnInit, ElementRef, Optional } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
|
@ -31,7 +31,7 @@ export class CoreAutoFocusDirective implements OnInit {
|
|||
protected element: HTMLElement;
|
||||
|
||||
constructor(element: ElementRef, private domUtils: CoreDomUtilsProvider, private utils: CoreUtilsProvider,
|
||||
private navCtrl: NavController) {
|
||||
@Optional() private navCtrl: NavController) {
|
||||
this.element = element.nativeElement || element;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Directive, Input, OnInit, ElementRef } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreFileHelperProvider } from '../providers/file-helper';
|
||||
import { CoreDomUtilsProvider } from '../providers/utils/dom';
|
||||
import { CoreUtilsProvider } from '../providers/utils/utils';
|
||||
|
|
|
@ -62,7 +62,7 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
private textUtils: CoreTextUtilsProvider, private translate: TranslateService, private platform: Platform,
|
||||
private utils: CoreUtilsProvider, private urlUtils: CoreUrlUtilsProvider, private loggerProvider: CoreLoggerProvider,
|
||||
private filepoolProvider: CoreFilepoolProvider, private appProvider: CoreAppProvider,
|
||||
private contentLinksHelper: CoreContentLinksHelperProvider, private navCtrl: NavController,
|
||||
private contentLinksHelper: CoreContentLinksHelperProvider, @Optional() private navCtrl: NavController,
|
||||
@Optional() private content: Content) {
|
||||
this.element = element.nativeElement;
|
||||
this.element.classList.add('opacity-hide'); // Hide contents until they're treated.
|
||||
|
|
|
@ -39,7 +39,7 @@ export class CoreLinkDirective implements OnInit {
|
|||
|
||||
constructor(element: ElementRef, private domUtils: CoreDomUtilsProvider, private utils: CoreUtilsProvider,
|
||||
private sitesProvider: CoreSitesProvider, private urlUtils: CoreUrlUtilsProvider,
|
||||
private contentLinksHelper: CoreContentLinksHelperProvider, private navCtrl: NavController,
|
||||
private contentLinksHelper: CoreContentLinksHelperProvider, @Optional() private navCtrl: NavController,
|
||||
@Optional() private content: Content) {
|
||||
// This directive can be added dynamically. In that case, the first param is the anchor HTMLElement.
|
||||
this.element = element.nativeElement || element;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Directive, Input, OnInit, ElementRef } from '@angular/core';
|
||||
import { Directive, Input, OnInit, ElementRef, Optional } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
|
||||
/**
|
||||
|
@ -27,7 +27,7 @@ export class CoreUserLinkDirective implements OnInit {
|
|||
|
||||
protected element: HTMLElement;
|
||||
|
||||
constructor(element: ElementRef, private navCtrl: NavController) {
|
||||
constructor(element: ElementRef, @Optional() private navCtrl: NavController) {
|
||||
// This directive can be added dynamically. In that case, the first param is the anchor HTMLElement.
|
||||
this.element = element.nativeElement || element;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue