从服务访问组件数据

时间:2019-07-10 16:37:22

标签: angular typescript

我在Angular 7中有一个调用API的服务,并且我想使用API​​调用中组件收集的一些数据。这是组件的相关部分:

import { Component, OnInit } from "@angular/core";
import { IPrompt } from './prompt';
import { PromptService } from './prompt.service';
import { DropdownService } from '../dropdown.service'
import { FormGroup, FormControl, ReactiveFormsModule } from '@angular/forms';
import { IQuery } from './prompt'
import { NgxSpinnerService } from 'ngx-spinner';

import { Query } from '../dropdown.service';


@Component({
  selector: 'pm-prompts',
  templateUrl: './prompt-list.component.html',
  styleUrls: ['./prompt-list.component.css']
})

export class PromptListComponent implements OnInit 
{

  public get searchArray(): string[] 
  {
  return [ this.searchForm.controls['searchQuery'].value, this.searchForm.controls['region'].value, 
  this.searchForm.controls['status'].value, this.searchForm.controls['language'].value, 
  this.searchForm.controls['inputMode'].value ];
  }

  public get QueryString(): string
  { 
    var query = new Query(this.searchForm.controls['searchQuery'].value, this.searchForm.controls['region'].value, 
    this.searchForm.controls['status'].value, this.searchForm.controls['language'].value, 
    this.searchForm.controls['inputMode'].value, this.searchArray);
    return query.getQuery;
  }
}

我从上述示例中删除了所有不必要的字段。基本上,我想从名为PromptService的服务访问此组件中的get QueryString()方法。如果需要,我也可以包括该服务的代码。我已经对此进行了研究,但是我看到的所有问题都询问了如何在组件中使用服务中的数据,而不是相反。

我尝试将组件导入服务,然后使用:

queryString = PromptListComponent.QueryString()

但是我收到一条错误消息,指出“类型'ProoftListComponent'的类型不存在属性'QueryString'”。我觉得有一个简单的解决方法,但是我没有运气找到它或弄清楚它。

3 个答案:

答案 0 :(得分:2)

您可以将组件导入服务,并在构造函数中对其进行定义,它会生成该组件的实例,然后可以从该组件的实例访问方法和属性:

在您的服务文件中:

import { PromptListComponent } from './path-to-your-component';
import { Injectable } from '@angular/core';

@Injectable({providedIn:'root'}) //Or import to providers
export class PromptService {
 //Define it in your service constructor
 constructor( private promptListComponent: PromptListComponent){}

 //You now have generated an instance of that component
 getQueryFromPromtListComponent() {
   console.log(this.promptListComponent.QueryString())
 }
}

答案 1 :(得分:2)

您看到的所有内容都是关于从组件中的服务访问数据的原因,是因为您已反转控件。您的逻辑应该是组件正在将这些数据推向服务,而不是服务正在从您的组件中拉取数据。

您的理论服务应该具有一种data=['msg3', 'msg4']方法,该方法接受查询字符串作为参数,并且只要查询字符串发生更改,您的组件就会调用该服务方法。因为您已经在使用反应形式,所以这很简单!

@patch('Client')
def test_client_returns_correct_messages(self, MockClient):
    MockWebClient.get_messages.side_effects = [
    Mock(name='response',
         data={'messages': received_messages,
               'has_more': True}),
    Mock(name='response',
         data={'messages': received_messages,
               'has_more': False})]

messages = client.get_messages()

有很多其他方法可以做到这一点,但是原理应该是相同的,数据总是被推入,而从未被拉出。

答案 2 :(得分:1)

假设您不是在侦听UI中的事件,而是在服务中执行需要获取组件属性的操作。

我正在利用 Visitor 模式实现此解决方案。

根据提供的示例代码,您似乎缺少了几件事。

  1. 无法通过类类型访问属性,只能使用静态成员来完成。
  2. 要访问属性(非静态),您需要获取组件实例。它需要传递给服务。

好了,现在我们有一些需要处理的背景,让我们看看一种可能的方法来实现您想要的目标:

  1. 通过构造函数将服务(PromptService)作为依赖项添加到组件。这将帮助您的服务直接引用您的UI组件。
  2. 创建一个组件将实现的接口,该接口将定义一个接收属性名称的函数,该属性名称必须返回值。
public interface IPropertyReader {
   readProperty<T>(prop: string): T
}
  1. 该函数将用于将指定的属性值返回给调用服务。
@Component({
  selector: 'pm-prompts',
  templateUrl: './prompt-list.component.html',
  styleUrls: ['./prompt-list.component.css']
})

export class PromptListComponent implements OnInit, IPropertyReader
{
   constructor(private promptService: PromptService) {
      promptService.registerComponent(this)
   }
   public readProperty<T>(prop: string):T {
      if (!this.hasOwnProperty(prop)) {
         throw Error(`Property "${prop}" does not exists`);
      }
      return this[prop];
   }   
}
  1. 通过添加接收组件实例的函数来修改服务,但参数类型必须是上述第2点的接口。
@Injectable({ providedIn: 'root' }) 
export class PromptService {
  component: IPropertyReader
  public registerComponent(comp: IPropertyReader) {
     this.component = comp;
     console.log(this.component.readProperty<string>("QueryString"));
  }
}