Nativescript ModalDialogService,无法绑定到组件上的文本

Nativescript ModalDialogService,无法绑定到组件上的文本,nativescript,angular2-nativescript,Nativescript,Angular2 Nativescript,与ModalDialogService相关的一些内容正在阻止组件上在模式中呈现的某些内容无法正常工作 我可以将tap事件绑定到组件上的函数,如示例所示,并且可以通过组件中的按钮关闭模式 但如果将标签绑定到组件上的属性,则不会显示任何内容。在我的应用程序的任何其他地方都会显示相同的代码 我怀疑这与必须使用entryComponents来注册组件有关,但我不知道发生了什么 import { NgModule, ModuleWithProviders } from '@angular/core'; i

与ModalDialogService相关的一些内容正在阻止组件上在模式中呈现的某些内容无法正常工作

我可以将tap事件绑定到组件上的函数,如示例所示,并且可以通过组件中的按钮关闭模式

但如果将标签绑定到组件上的属性,则不会显示任何内容。在我的应用程序的任何其他地方都会显示相同的代码

我怀疑这与必须使用entryComponents来注册组件有关,但我不知道发生了什么

import { NgModule, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common';

/* Nativescript modules */
import { NativeScriptFormsModule } from 'nativescript-angular/forms';
import { NativeScriptModule } from 'nativescript-angular/nativescript.module';
import { NativeScriptRouterModule } from 'nativescript-angular/router';
import { ModalDialogService } from 'nativescript-angular/modal-dialog';
import { registerElement } from 'nativescript-angular/element-registry';
registerElement('CardView', () => require('nativescript-cardview').CardView);
/* End nativescript modules */

import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { LoginPageComponent } from './containers/login-page/login-page.component';
import { RegisterPageComponent } from './containers/register-page/register-page.component';
import { ForgotPasswordPageComponent } from './containers/forgot-password-page/forgot-password-page.component';
import { LoginFormComponent } from './components/login-form/login-form.component';
import { RegisterFormComponent } from './components/register-form/register-form.component';
import { ForgotPasswordFormComponent } from './components/forgot-password-form/forgot-password-form.component';
import { TermsComponent } from './components/terms/terms.component';

import { AuthService } from './services/auth.service';
import { AuthGuard, LazyAuthGuard } from './services/auth-guard.service';
import { AuthEffects } from './effects/auth.effects';
import { reducers } from './reducers';

import { AuthRoutingModule } from './auth-routing.module';

export const COMPONENTS = [
  LoginPageComponent,
  RegisterPageComponent,
  ForgotPasswordPageComponent,
  LoginFormComponent,
  RegisterFormComponent,
  ForgotPasswordFormComponent,
  TermsComponent,
];

@NgModule({
  imports: [
    CommonModule,
    NativeScriptModule,
    NativeScriptRouterModule,
    NativeScriptFormsModule,
  ],
  declarations: COMPONENTS,
  exports: COMPONENTS,
  entryComponents: [TermsComponent],
  providers: [

     ModalDialogService
   ]
})
export class AuthModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: RootAuthModule,
      providers: [AuthService, AuthGuard, LazyAuthGuard],
    };
  }
}

@NgModule({
  imports: [
    AuthModule,
    AuthRoutingModule,
    StoreModule.forFeature('auth', reducers),
    EffectsModule.forFeature([AuthEffects]),
  ],
})
export class RootAuthModule {}






import { Component } from '@angular/core';
import { ModalDialogParams } from 'nativescript-angular/modal-dialog';
import { Page } from 'ui/page';
@Component({
  moduleId: module.id,
  selector: 'terms-dialog',
  templateUrl: 'terms.component.html',
})
export class TermsComponent  {
  public test = 'sdfsdfsdfsd';
  constructor(private params: ModalDialogParams, private page: Page) {
    this.page.on('unloaded', () => {
      // using the unloaded event to close the modal when there is user interaction
      // e.g. user taps outside the modal page
      this.params.closeCallback();
    });  
  }
  public getText(){
    return 'some text';
  }
  public close() {
    debugger;
    this.params.closeCallback();
  } 
}

<ScrollView sdkExampleTitle sdkToggleNavButton>
  <StackLayout>
    <Label horizontalAlignment="left" text="test" class="m-15 h2" textWrap="true"></Label>
    <Label horizontalAlignment="left" [text]="test" class="m-15 h2" textWrap="true"></Label>
    <Label [text]="getText()" horizontalAlignment="left" class="m-15 h2" textWrap="true"></Label>
     <Button row="0" col="1" horizontalAlignment="right" text="&#xf2d4;" class="fa" id="menu-btn" (tap)="close()"></Button>
  </StackLayout>
</ScrollView>







import {
  Component,
  OnInit,
  Input,
  Output,
  EventEmitter,
  ViewContainerRef,
} from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { Register } from '../../models/user';
import { Config } from '../../../common/index';
import { TermsComponent } from '../terms/terms.component';

/* Mobile Specific Stuff */
import imagepicker = require('nativescript-imagepicker');
import {
  ModalDialogService,
  ModalDialogOptions,
} from 'nativescript-angular/modal-dialog';

@Component({
  moduleId: module.id,
  selector: 'bc-register-form',
  templateUrl: 'register-form.component.html',
  styleUrls: ['register-form.component.scss'],
})
export class RegisterFormComponent implements OnInit {
  @Input()
  set pending(isPending: boolean) {
    if (isPending) {
      this.form.disable();
    } else {
      this.form.enable();
    }
  }

  @Input() errorMessage: string | null;

  @Output() submitted = new EventEmitter<Register>();

  form: FormGroup = new FormGroup({
    username: new FormControl(''),
    password: new FormControl(''),
    email: new FormControl(''),
    avatar: new FormControl(''),
  });

  avatarFilePreview: any;

  constructor(
    public modalService: ModalDialogService,
    private viewContainer: ViewContainerRef
  ) {}

  ngOnInit() {
    this.form.get('avatar').valueChanges.subscribe(v => {
      this.avatarFilePreview = v._files[0];
    });
  }

  openDialog() {
    const options: ModalDialogOptions = {
      fullscreen: false,
      viewContainerRef: this.viewContainer,
      context: {}
    };

    return this.modalService.showModal(TermsComponent, options);
  }

  getNativescriptImagePicker() {
    let context = imagepicker.create({
      mode: 'single',
    });
    var self = this;
    context
      .authorize()
      .then(function() {
        return context.present();
      })
      .then(function(selection) {
        self.avatarFilePreview = selection[0];
      })
      .catch(function(e) {
        // process error
      });
  }

  submit() {
    if (this.form.valid) {
      this.submitted.emit(this.form.value);
    }
  }
}


{
  "name": "snapnurse-apps",
  "version": "0.0.0",
  "repository": "<fill-your-repository-here>",
  "nativescript": {
    "id": "com.domain.project",
    "tns-android": {
      "version": "3.2.0"
    },
    "tns-ios": {
      "version": "3.2.0"
    }
  },
  "dependencies": {
    "@angular/animations": "~4.1.0",
    "@angular/common": "~4.1.0",
    "@angular/compiler": "~4.1.0",
    "@angular/core": "~4.1.0",
    "@angular/forms": "~4.1.0",
    "@angular/http": "~4.1.0",
    "@angular/platform-browser": "~4.1.0",
    "@angular/platform-browser-dynamic": "~4.1.0",
    "@angular/router": "~4.1.0",
    "@ngrx/db": "^2.0.2",
    "@ngrx/effects": "^4.1.0",
    "@ngrx/entity": "^4.1.0",
    "@ngrx/router-store": "^4.1.0",
    "@ngrx/store": "^4.1.0",
    "@ngrx/store-devtools": "^4.0.0",
    "@ngx-translate/core": "^6.0.1",
    "@ngx-translate/http-loader": "0.0.3",
    "nativescript-angular": "^3.1.0",
    "nativescript-cardview": "^2.0.3",
    "nativescript-imagepicker": "^4.0.1",
    "nativescript-ngx-fonticon": "^3.0.0",
    "nativescript-theme-core": "~1.0.2",
    "ngrx-store-freeze": "^0.2.0",
    "reflect-metadata": "~0.1.8",
    "rxjs": "^5.4.0",
    "tns-core-modules": "^3.3.0",
    "zone.js": "~0.8.2"
  },
  "devDependencies": {
    "@angular/compiler-cli": "~4.1.0",
    "@ngtools/webpack": "~1.5.5",
    "@types/jasmine": "^2.5.47",
    "babel-traverse": "6.25.0",
    "babel-types": "6.25.0",
    "babylon": "6.17.4",
    "copy-webpack-plugin": "~4.0.1",
    "css-loader": "0.28.2",
    "del": "^2.2.2",
    "extract-text-webpack-plugin": "~2.1.0",
    "gulp": "gulpjs/gulp#4.0",
    "gulp-debug": "^3.1.0",
    "gulp-rename": "^1.2.2",
    "gulp-string-replace": "^0.4.0",
    "lazy": "1.0.11",
    "nativescript-css-loader": "~0.26.0",
    "nativescript-dev-android-snapshot": "^0.*.*",
    "nativescript-dev-sass": "^1.3.2",
    "nativescript-dev-typescript": "~0.4.5",
    "nativescript-dev-webpack": "^0.7.3",
    "raw-loader": "~0.5.1",
    "resolve-url-loader": "~2.0.2",
    "typescript": "~2.3.4",
    "webpack": "^3.7.1",
    "webpack-bundle-analyzer": "^2.8.2",
    "webpack-sources": "~0.2.3"
  },
  "scripts": {
    "prepPhone": "gulp build.Phone",
    "prepTablet": "gulp build.Default",
    "prepCLIPhone": "gulp build.cli.Phone",
    "prepCLITablet": "gulp build.cli.Default",
    "ios": "npm run prepCLITablet && tns run ios",
    "ios.phone": "npm run prepCLIPhone && tns run ios",
    "android": "npm run prepCLITablet && tns run android",
    "android.phone": "npm run prepCLIPhone && tns run android",
    "phone-ios-bundle": "npm run prepPhone && tns prepare ios && npm run start-ios-bundle --uglify",
    "tablet-ios-bundle": "npm run prepTablet && tns prepare ios && npm run start-ios-bundle --uglify",
    "build.phone-ios-bundle": "npm run prepPhone && tns prepare ios && npm run build-ios-bundle --uglify",
    "build.tablet-ios-bundle": "npm run prepTablet && tns prepare ios && npm run build-ios-bundle --uglify",
    "phone-android-bundle": "npm run prepPhone && tns prepare android && npm run start-android-bundle --uglify",
    "tablet-android-bundle": "npm run prepTablet && tns prepare android && npm run start-android-bundle --uglify",
    "build.phone-android-bundle": "npm run prepPhone && tns prepare android && npm run build-android-bundle --uglify",
    "build.tablet-android-bundle": "npm run prepTablet && tns prepare android && npm run build-android-bundle --uglify",
    "ns-bundle": "ns-bundle",
    "livesync": "gulp tns.Livesync",
    "livesync.phone": "gulp tns.Livesync.Phone",
    "publish-ios-bundle": "npm run ns-bundle --ios --publish-app",
    "generate-android-snapshot": "generate-android-snapshot --targetArchs arm,arm64,ia32 --install",
    "start-android-bundle": "npm run ns-bundle --android --run-app",
    "start-ios-bundle": "npm run ns-bundle --ios --run-app",
    "build-android-bundle": "npm run ns-bundle --android --build-app",
    "build-ios-bundle": "npm run ns-bundle --ios --build-app"
  }
}

在花了几个小时追踪这个问题之后,我想出了一个解决方法

创建一个名为CustomDialogService的类:

import {
  DetachedLoader,
  ModalDialogOptions,
  ModalDialogParams,
  ModalDialogService,
  PAGE_FACTORY,
  PageFactory
} from "nativescript-angular";
import {
  ComponentFactoryResolver,
  ComponentRef,
  Injectable,
  ReflectiveInjector,
  Type,
  ViewContainerRef
} from "@angular/core";
import {View} from "tns-core-modules/ui/core/view";
import {Page} from "tns-core-modules/ui/page";

interface ShowDialogOptions {
  containerRef: ViewContainerRef;
  context: any;
  doneCallback: any;
  fullscreen: boolean;
  pageFactory: PageFactory;
  parentPage: Page;
  resolver: ComponentFactoryResolver;
  type: Type<any>;
}

@Injectable()
export class CustomDialogService implements ModalDialogService {
  private static showDialog({
                              containerRef,
                              context,
                              doneCallback,
                              fullscreen,
                              pageFactory,
                              parentPage,
                              resolver,
                              type,
                            }: ShowDialogOptions): void {
    const page = pageFactory({isModal: true, componentType: type});

    let detachedLoaderRef: ComponentRef<DetachedLoader>;
    const closeCallback = (...args: any[]) => {
      doneCallback.apply(undefined, args);
      page.closeModal();
      detachedLoaderRef.instance.detectChanges();
      detachedLoaderRef.destroy();
    };

    const modalParams = new ModalDialogParams(context, closeCallback);

    const providers = ReflectiveInjector.resolve([
      {provide: Page, useValue: page},
      {provide: ModalDialogParams, useValue: modalParams},
      {provide: ViewContainerRef, useValue: containerRef}
    ]);

    const childInjector = ReflectiveInjector.fromResolvedProviders(
      providers, containerRef.parentInjector);
    const detachedFactory = resolver.resolveComponentFactory(DetachedLoader);
    detachedLoaderRef = containerRef.createComponent(detachedFactory, -1, childInjector);
    detachedLoaderRef.instance.loadComponent(type).then((compRef) => {
      compRef.changeDetectorRef.detectChanges();
      const componentView = <View>compRef.location.nativeElement;

      if (componentView.parent) {
        (<any>componentView.parent).removeChild(componentView);
      }

      page.content = componentView;
      parentPage.showModal(page, context, closeCallback, fullscreen);
    });
  }

  public showModal(type: Type<any>,
                   {viewContainerRef, moduleRef, context, fullscreen}: ModalDialogOptions): Promise<any> {
    if (!viewContainerRef) {
      throw new Error(
        "No viewContainerRef: " +
        "Make sure you pass viewContainerRef in ModalDialogOptions."
      );
    }

    const parentPage: Page = viewContainerRef.injector.get(Page);
    const pageFactory: PageFactory = viewContainerRef.injector.get(PAGE_FACTORY);

    // resolve from particular module (moduleRef)
    // or from same module as parentPage (viewContainerRef)
    const componentContainer = moduleRef || viewContainerRef;
    const resolver = componentContainer.injector.get(ComponentFactoryResolver);

    return new Promise(resolve => {
      setTimeout(() => CustomDialogService.showDialog({
        containerRef: viewContainerRef,
        context,
        doneCallback: resolve,
        fullscreen: !!fullscreen,
        pageFactory,
        parentPage,
        resolver,
        type,
      }), 10);
    });
  }
}
然后,在NgModule中,将此提供程序添加到提供程序阵列:

{提供:ModalDialogService,useClass:CustomDialogService}


这将使用新的CustomDialogService覆盖默认的ModalDialogService,从而修复错误

嗨,乔希。你有一些代码可以共享吗?@Alexziskin当然有,不过可能不会有帮助,因为它和文档一样。需要真正思考是什么导致了它,而不是查看所有代码以找出是什么导致了它。@AlexZiskind我已经添加了auth模块和相关的components@AlexZiskind第一个标签显示正确,因为文本是硬编码的。第二个和第三个标签根本不显示。然后该按钮点击关闭函数中的调试器。怎么会这样?还没有调试,但是你在AuthModule中包含了NativeScriptModule吗?你好,vultix。我也面临同样的问题。我遵循了您的解决方案,但我得到了以下错误:错误:承诺中的未捕获:错误:StaticInjectorErrorAppModule[Test2Component->CustomDialogService]。你有什么想法吗?@MadNeox上面的提供者:{provide:ModalDialogService,useClass:CustomDialogService}不提供CustomDialogService类。它将ModalDialogService替换为CustomDialogService。要使用自定义服务,请将ModalDialogService而不是CustomDialogService插入应用程序。它将被自定义代码覆盖。