Angular2订阅总是出现空值

时间:2016-08-09 20:17:42

标签: angular angular2-observables

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

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

有人可以帮我理解我在这里缺少的东西吗?

个人资料-input.component

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}]);
 }

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);
    }
 }

个人资料-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);
   }
 }

2 个答案:

答案 0 :(得分:0)

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

到达时,将调用此回调
 ngOnInit() {
    this.profileService.pushedData.subscribe(
        (value: Profile) => {
            this.profile = value;
            console.log("this.profile in img upload is");
            console.log(this.profile);
        });
     }
 }

答案 1 :(得分:0)

我遇到的问题是由于对如何使用可观察量的误解。我正在重定向到另一个页面(使用新组件重新加载新模板)以从配置文件数据到我想要上传图像的区域。这是一个有缺陷的概念。我修复它的方法是执行以下操作: 删除上载的第二个组件和模板,并将所有代码合并到配置文件创建组件中 添加一些ngIf语句以确定何时基于用户完成不同任务来显示简档创建页面的不同区域(即,输入简档信息并创建简档对象,添加照片,添加视频)。 通过做这些事情,我总是在同一页面上,所以我可以引用1个动作的结果在另一个中使用,并且随着事情的完成,我可以设置变量来控制应用程序的状态以及向用户显示的内容。 模板的最终代码如下: &lt; script src =&#34; profile-input.component.ts&#34;&gt;&lt; / script&gt; &lt; section class =&#34; col-md-8 col-md-offset-2&#34;&gt;   &lt; form [hidden] =&#34; formSubmitted&#34; [formGroup] =&#34; profileForm&#34; (ngSubmit)=&#34;的onSubmit()&#34;&GT;     &lt; div class =&#34; row&#34;&gt;       &lt; div class =&#34; col-xs-12&#34;&gt;         &lt; div class =&#34; form-group&#34;&gt;           &lt; label for =&#34; first_name&#34;&gt;名字&lt; / label&gt;           &LT;输入             类型=&#34;文本&#34;             ID =&#34;如first_name&#34;             类=&#34;形状控制&#34;             formControlName =&#34;如first_name&#34;&GT;         &LT; / DIV&GT;       &LT; / DIV&GT;     &LT; / DIV&GT;     &lt; div class =&#34; row&#34;&gt;       &lt; div class =&#34; col-xs-12&#34;&gt;         &lt; div class =&#34; form-group&#34;&gt;           &lt; label for =&#34; last_name&#34;&gt;姓氏&lt; / label&gt;           &LT;输入             类型=&#34;文本&#34;             ID =&#34;姓氏&#34;             类=&#34;形状控制&#34;             formControlName =&#34;姓氏&#34;&GT;         &LT; / DIV&GT;       &LT; / DIV&GT;     &LT; / DIV&GT;     &lt; div class =&#34; row&#34;&gt;       &LT;标签&gt;&的UserType LT; /标签&gt;       &lt; input type =&#34; checkbox&#34; ID =&#34;生产者&#34;类=&#34;形状控制&#34; formControlName =&#34;生产者&#34; &GT;制作&LT峰; br&GT;       &lt; input type =&#34; checkbox&#34; ID =&#34;客户机&#34;类=&#34;形状控制&#34; formControlName =&#34;客户机&#34; &GT;客户&LT峰; br&GT;       &lt; input type =&#34; checkbox&#34; ID =&#34;创意&#34;类=&#34;形状控制&#34; formControlName =&#34;创意&#34; &GT;广告&lt; BR&GT;     &LT; / DIV&GT;     &lt; button type =&#34;提交&#34; class =&#34; btn btn-primary&#34; [无效] =&#34;!profileForm.valid&#34; &gt; {{!个人资料? &#39;添加个人资料&#39; :&#39;保存个人资料&#39; }}&LT; /按钮&GT;     &lt; button type =&#34; button&#34; class =&#34; btn btn-danger&#34; (点击)=&#34; onCancel()&#34; * ngIf =&#34;轮廓&#34;&GT;取消&LT; /按钮&GT;   &LT; /形式&GT; &LT; /节&gt; &lt;! - 图片上传开始 - &gt; &lt; section [hidden] =&#34;!imgUploadVisible&#34; class =&#34; col-md-8 col-md-offset-2&#34;&gt;   &lt; h2 * ngIf =&#34; createdProfile&#34;&gt;欢迎{{createdProfile.first_name}}!&lt; / h2&gt;   &lt; p&gt;现在让我们来看看你。&lt; / p&gt;   &LT; HR&GT;   &lt; h2&gt;个人资料图片上传&lt; / h2&gt;   &lt; input type =&#34; file&#34; (变化)=&#34; imgFileChangeEvent($事件)&#34;占位符=&#34;上传文件...&#34; /&GT;   &LT峰; br&GT;   &lt; button type =&#34; button&#34; (点击)=&#34; uploadImg()&#34;&gt;上传图片&lt; / button&gt;   &LT; HR&GT;   &lt; div * ngIf =&#34; uploadFile&#34; &GT;     上传的文件路径:{{uploadFile}}   &LT; / DIV&GT;   &lt; div class =&#34; row&#34;&gt;     &lt; div class =&#34; col-xs-12&#34;&gt;       &lt; div class =&#34; img&#34; * ngIf =&#34; uploadFile&#34;&GT;         &lt; img [src] =&#34; uploadFile&#34;宽度=&#34; 200像素&#34; ALT =&#34;&#34;&GT;       &LT; / DIV&GT;     &LT; / DIV&GT;   &LT; / DIV&GT;   &LT峰; br&GT;   &lt; button [hidden] =&#34;!uploadFile&#34;类型=&#34;按钮&#34; (点击)=&#34; sendToS3()&#34;&gt;发送到S3&lt; / button&gt;   &LT; HR&GT;   &lt; div * ngIf =&#34; s3LocString&#34;&gt;     S3位置:{{s3LocString}}     &LT峰; br&GT;     &lt; img [src] =&#34; s3LocString&#34;宽度=&#34; 200像素&#34; ALT =&#34;&#34;&GT;   &LT; / DIV&GT;   &lt; button type =&#34; button&#34; (点击)=&#34; imgUploadComplete()&#34;&gt;接下来&LT; /按钮&GT; &LT; /节&gt; &lt;! - 图片上传END - &gt; &lt;! - 视频上传开始 - &gt; &lt; section [hidden] =&#34;!vidUploadVisible&#34; class =&#34; col-md-8 col-md-offset-2&#34;&gt;   &lt; h2&gt;上传个人资料视频&lt; / h2&gt;   &lt; p&gt;现在告诉我们你可以做些什么。&lt; / p&gt;   &LT; HR&GT;   &lt; h2&gt;演示视频上传&lt; / h2&gt;   &lt; input type =&#34; file&#34; (变化)=&#34; vidFileChangeEvent($事件)&#34;占位符=&#34;上传文件...&#34; /&GT;   &LT峰; br&GT;   &lt; button type =&#34; button&#34; (点击)=&#34; uploadVid()&#34;&gt;上传视频&lt; / button&gt;   &LT; HR&GT;   &lt; div * ngIf =&#34; vidUploadFile&#34; &GT;     上传的文件路径:{{vidUploadFile}}   &LT; / DIV&GT;   &lt; div class =&#34; row&#34;&gt;     &lt; div class =&#34; col-xs-12&#34;&gt;       &lt; div class =&#34; vid&#34; * ngIf =&#34; vidUploadFile&#34;&GT;         &lt;视频自动播放控件[src] =&#34; vidUploadFile&#34;&gt;&lt; / video&gt;       &LT; / DIV&GT;     &LT; / DIV&GT;   &LT; / DIV&GT; &LT; /节&gt; 配置文件输入组件的重要部分如下:   uploadImg(){     console.log(&#39; this.createdProfile上传之前&#39;);     的console.log(this.createdProfile);     this.uploadFileService.makeFileRequest(&#34; http:// localhost:3000 / upload&#34;,this.createdProfile.profileId,this.imgFilesToUpload,&#39; profileImg&#39;)       。订阅(         (结果)=&gt; {           console.log(&#39;导致删除了prof输入操作的结果是&#39;);           的console.log(结果);            this.imageUploaded = true;            this.formSubmitted = true;            this.uploadFile = result.obj.path;            this.uploadObject = result.obj         },         (错误)=&gt; {           console.log(&#39;我们错误&#39;);           console.error(误差);         });   }   uploadVid(){     console.log(&#39; this.createdProfile上传之前&#39;);     的console.log(this.createdProfile);     this.uploadFileService.makeFileRequest(&#34; http:// localhost:3000 / upload&#34;,this.createdProfile.profileId,this.vidFilesToUpload,&#39; profileVideo&#39;)       。订阅(         (结果)=&gt; {           console.log(&#39;导致删除了prof输入操作的结果是&#39;);           的console.log(结果);           this.vidUploaded = true;           this.vidUploadFile = result.obj.path;           this.vidUploadObject = result.obj         },         (错误)=&gt; {           console.log(&#39;我们错误&#39;);           console.error(误差);         });   }   sendToS3(){     console.log(&#39;上传到S3&#39;);     的console.log(this.uploadObject);     this.uploadFileService.sendToS3(this.uploadObject,this.createdProfile.profileId,this.uploadObject._id)       。订阅(         data =&gt; {           的console.log(数据);           this.s3Location = data;           this.s3LocString = data.Location;         },         错误=&gt; {           的console.log(误差);         }       );   } 希望这有助于其他人更好地理解这些概念。