1

我有一个我认为是相当简单的设置。我正在配置文件输入组件中创建用户配置文件。然后在提交表单并创建用户后,我想将用户发送到 profile-img-upload 组件以添加照片。我的理解是,通过将创建的配置文件保存到配置文件服务中,然后在 img-upload 组件中调用该配置文件来完成这是有意义的。但是我遗漏了一些东西,因为当我到达 img-upload 组件console.log(this.profile)时,配置文件始终为空。

我觉得我在这里误解了订阅和可观察的一些非常核心的东西。我要做的就是在第一个组件上创建一个 Profile 对象,然后将创建的 Profile 传递给第二个组件,然后才能上传照片并将其分配给 Profile。

有人可以帮我理解我在这里缺少什么吗?

配置文件输入组件

import...

@Component({
  moduleId: module.id,
  selector: 'my-profile-input',
  templateUrl: 'profile-input.template.html',
  directives: [REACTIVE_FORM_DIRECTIVES]
 })

export class ProfileInputComponent implements OnInit {
 @Output() profile: Profile;
 profile: Profile = null;

constructor(private formBuilder:FormBuilder,
            private profileSrevice: ProfileService,
            private errorService: ErrorService,
            private router: Router,
            private route: ActivatedRoute) {}

 onSubmit() {
 const profile: Profile = new Profile(
            this.profileForm.value.first_name,
            this.profileForm.value.last_name  
 );

 this.profileSrevice.addProfile(profile)
            .subscribe(
                data => {
                    console.log('what comes back from addProfile is: ' + JSON.stringify(data));
                    this.profileSrevice.profiles.push(data);

                    // The line below will superceded the one above.
                    this.profileSrevice.pushData(data);
                },
                error => this.errorService.handleError(error)
            );
        this.router.navigate(['profile-img-upload', {myProfile: this.profile}]);
 }

配置文件.service.ts

 import...

 @Injectable()
 export class ProfileService {
    pushedData = new EventEmitter<Profile>();

    pushData(value: Profile) {
     this.pushedData.emit(value);
     console.log('value in service is ');
     console.log(value);
    }
 }

profile-img-upload.component.ts

import...

@Component({
 moduleId: module.id,
 selector: 'my-profile-img-upload',
 templateUrl: 'profile-img-upload.template.html',
 directives: [ ROUTER_DIRECTIVES, FILE_UPLOAD_DIRECTIVES, NgClass, NgStyle, CORE_DIRECTIVES, FORM_DIRECTIVES ],
 providers: [AWSUploadService, UploadFileService]
})

export class ProfileImgUploadComponent implements OnInit {
  @Input() myProfile: Profile;
  profile: Profile;

  constructor(private uploadFileService: UploadFileService,
            private route: ActivatedRoute,
            private profileService: ProfileService,
            private errorService: ErrorService) {
    this.filesToUpload = [];}

  ngOnInit() {
    this.profileService.pushedData.subscribe(
        (value: Profile) => this.profile
    );

    console.log("this.profile in img upload is");
    console.log(this.profile);
   }
 }
4

2 回答 2

0

您必须将引用从订阅返回的数据的代码移动到订阅回调中。当数据从可观察对象到达时调用此回调

 ngOnInit() {
    this.profileService.pushedData.subscribe(
        (value: Profile) => {
            this.profile = value;
            console.log("this.profile in img upload is");
            console.log(this.profile);
        });
     }
 }
于 2016-08-09T20:30:27.317 回答
0

我遇到的问题是由于对如何使用 observables 的误解。我正在重定向到不同的页面(重新加载带有新组件的新模板)以从配置文件数据获取我想要上传图像的区域。这是一个有缺陷的概念。我修复它的方法是执行以下操作:

  1. 删除用于上传的第二个组件和模板,并将所有代码合并到配置文件创建组件中

  2. 添加一些 ngIf 语句以确定何时根据用户完成不同任务(即输入个人资料信息和创建个人资料对象、添加照片、添加视频)来显示个人资料创建页面的不同区域。

通过做这些事情,我总是在同一个页面上,所以我可以引用一个操作的结果以在另一个操作中使用,并且随着事情的完成,我可以设置变量来控制应用程序的状态以及向用户显示的内容。

模板的最终代码如下:

<script src="profile-input.component.ts"></script>
<section class="col-md-8 col-md-offset-2">
  <form [hidden]="formSubmitted" [formGroup]="profileForm" (ngSubmit)="onSubmit()">

    <div class="row">
      <div class="col-xs-12">
        <div class="form-group">
          <label for="first_name">First Name</label>
          <input
            type="text"
            id="first_name"
            class="form-control"
            formControlName="first_name">
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-12">
        <div class="form-group">
          <label for="last_name">Last name</label>
          <input
            type="text"
            id="last_name"
            class="form-control"
            formControlName="last_name">
        </div>
      </div>
    </div>


    <div class="row">
      <label>UserType</label>
      <input type="checkbox"  id="producer" class="form-control" formControlName="producer" >Producer<br>
      <input type="checkbox"  id="client"   class="form-control" formControlName="client" >Client<br>
      <input type="checkbox"  id="creative" class="form-control" formControlName="creative" >Creative<br>
    </div>


    <button type="submit" class="btn btn-primary" [disabled]="!profileForm.valid" >{{ !profile ? 'Add Profile' : 'Save Profile' }}</button>
    <button type="button" class="btn btn-danger" (click)="onCancel()" *ngIf="profile">Cancel</button>
  </form>
</section>

<!-- image upload START-->
<section [hidden]="!imgUploadVisible" class="col-md-8 col-md-offset-2">
  <h2 *ngIf="createdProfile">Welcome {{createdProfile.first_name}}!</h2>
  <p>Now lets get a look at you.</p>
  <hr>
  <h2>Profile Image Upload</h2>
  <input type="file" (change)="imgFileChangeEvent($event)" placeholder="Upload file..." />
  <br>
  <button type="button" (click)="uploadImg()">Upload Image</button>
  <hr>

  <div *ngIf="uploadFile" >
    Uploaded File Path: {{ uploadFile }}
  </div>
  <div class="row">
    <div class="col-xs-12">
      <div class="img" *ngIf="uploadFile">
        <img [src]="uploadFile" width="200px" alt="">
      </div>
    </div>
  </div>
  <br>
  <button [hidden]="!uploadFile" type="button" (click)="sendToS3()">Send TO S3</button>
  <hr>
  <div *ngIf="s3LocString">
    S3 Location: {{s3LocString}}
    <br>
    <img [src]="s3LocString" width="200px" alt="">
  </div>

  <button type="button" (click)="imgUploadComplete()">Next</button>

</section>
<!-- image upload END-->


<!-- Video upload START-->

<section [hidden]="!vidUploadVisible" class="col-md-8 col-md-offset-2">
  <h2>Upload Profile Video</h2>
  <p>Now show us what you can do.</p>
  <hr>
  <h2>Demo Video Upload</h2>
  <input type="file" (change)="vidFileChangeEvent($event)" placeholder="Upload file..." />
  <br>
  <button type="button" (click)="uploadVid()">Upload Video</button>
  <hr>

  <div *ngIf="vidUploadFile" >
    Uploaded File Path: {{ vidUploadFile }}
  </div>
  <div class="row">
    <div class="col-xs-12">
      <div class="vid" *ngIf="vidUploadFile">
        <video autoplay controls [src]="vidUploadFile"></video>

      </div>
    </div>
  </div>


</section>

profile-input 组件的重要部分如下:

  uploadImg() {
    console.log('this.createdProfile before upload');
    console.log(this.createdProfile);
    this.uploadFileService.makeFileRequest("http://localhost:3000/upload", this.createdProfile.profileId, this.imgFilesToUpload, 'profileImg')
      .subscribe(
        (result) => {
          console.log('result in prof input action removed is');
          console.log(result);
           this.imageUploaded = true;
           this.formSubmitted = true;
           this.uploadFile = result.obj.path;
           this.uploadObject = result.obj
        },
        (error) => {
          console.log('We are in error');
          console.error(error);
        });
  }

  uploadVid() {
    console.log('this.createdProfile before upload');
    console.log(this.createdProfile);
    this.uploadFileService.makeFileRequest("http://localhost:3000/upload", this.createdProfile.profileId, this.vidFilesToUpload, 'profileVideo')
      .subscribe(
        (result) => {
          console.log('result in prof input action removed is');
          console.log(result);
          this.vidUploaded = true;
          this.vidUploadFile = result.obj.path;
          this.vidUploadObject = result.obj
        },
        (error) => {
          console.log('We are in error');
          console.error(error);
        });
  }

  sendToS3() {
    console.log('uploading to S3');
    console.log(this.uploadObject);

    this.uploadFileService.sendToS3(this.uploadObject, this.createdProfile.profileId, this.uploadObject._id)
      .subscribe(
        data => {
          console.log(data);
          this.s3Location = data;
          this.s3LocString = data.Location;
        },
        error => {
          console.log(error);
        }
      );
  }

希望这有助于其他人更好地理解这些概念。

于 2016-09-09T20:20:19.057 回答