我想从子组件中通知父组件以更新父组件中的视图。我正在使用@Output注释执行此操作。
在父组件中,实际上调用了函数“ loadPosts()”,但视图未更新。有人知道为什么吗?
会发生什么:
父组件:
place_component.dart:
@Component(
selector: 'my-place',
directives: [coreDirectives,
formDirectives,
PostNewComponent,
PostListComponent,
MaterialButtonComponent,
MaterialDialogComponent,
ModalComponent,
MaterialTabPanelComponent,
MaterialTabComponent],
templateUrl: 'place_component.html',
styleUrls: ['place_component.css'],
providers: [materialProviders]
)
class PlaceComponent implements OnActivate, OnInit {
Place place;
final PlaceService _placeService;
final Location _location;
final ChangeDetectorRef cdRef;
int _id;
bool showBasicDialog = false;
final tabLabels = const <String>[
'Posts',
'Pictures',
'Pending Invitations'
];
PlaceComponent(this._placeService, this._location, this.cdRef);
@override
Future<void> onActivate(_, RouterState current) async {
_id = paths.getId(current.parameters);
loadPosts();
}
@override
Future<void> ngOnInit() async {
print("init executed");
}
Future<void> loadPosts() async {
if (_id != null) place = await (_placeService.get(_id));
cdRef.detectChanges();
print("loaded posts $_id");
}
void goBack() => _location.back();
Future<void> save() async {
await _placeService.update(place);
goBack();
}
}
place_component.html:
<div *ngIf="place != null">
<h2>{{place.name}}</h2>
<div class="grid">
<div class="col-1-3">
<div class="module">
<material-button class="open-post-button" (trigger)="showBasicDialog = true" [disabled]="showBasicDialog" raised>
New Post
</material-button>
</div>
</div>
<div class="col-2-3">
<div class="module">
<material-tab-panel class="tab-panel" [activeTabIndex]="0">
<material-tab label="Posts">
<div class="posts">
<div class="post">
<list-posts [place]="place"></list-posts>
</div>
</div>
</material-tab>
<material-tab label="Pictures">
Pictures
</material-tab>
<material-tab label="Videos">
Videos
</material-tab>
</material-tab-panel>
<div class="divider10"></div>
</div>
</div>
</div>
</div>
<modal [visible]="showBasicDialog">
<material-dialog class="basic-dialog">
<h1 header>New Post</h1>
<div class="new-post">
<new-post (doneIt)="loadPosts()" [place]="place"></new-post>
</div>
<div footer>
<material-button autoFocus clear-size (trigger)="showBasicDialog = false" class="close-button">
Close
</material-button>
</div>
</material-dialog>
</modal>
子组件
post_new_component.dart:
@Component(
selector: 'new-post',
directives: [coreDirectives,
formDirectives,
FileUploader,
materialInputDirectives,
MaterialButtonComponent],
templateUrl: 'post_new_component.html',
styleUrls: ['post_new_component.css'],
providers: [ClassProvider(PostService)]
)
class PostNewComponent {
final PostService _postService;
final _onDone = new StreamController.broadcast();
String postText;
Post post;
@Input()
Place place;
@Output()
Stream get doneIt => _onDone.stream;
PostNewComponent(this._postService);
Future<void> save() async {
await _postService.create(postText,place.id).then(((_) => _onDone.add(1)));
}
}
post_new_component.html:
<div class="post-new-component">
<div>
<material-input floatingLabel
multiline
rows="2"
maxRows="4"
label="Add a new post here...."
[(ngModel)]="postText"
class="post-text">
</material-input>
</div>
<div class="post-buttons">
<file-uploader class="file-uploader"></file-uploader>
<div><material-button (trigger)="save()" raised class="send-button">Post</material-button></div>
</div>
<div class="clear-float"></div>
</div>
我现在还根据此示例尝试使用EventBus:AngularDart: How do you pass an event from a Child component to a second level parent
PlaceComponent(this._placeService, this._location, this._postEvent, this.cdRef) {
_postEvent.onEventStream.listen((int id) => loadPosts().then((_){cdRef.markForCheck();}));
}
行为完全相同。已执行loadPosts函数,但视图未加载。
答案 0 :(得分:0)
我进行了以下设置:
要解决我的问题,我必须将事件发送给父组件,而不是父组件。所以@Output不会起作用。我只是将EventBus连接到另一个子组件。
因此,父组件的html看起来像这样:
...
<div><new-post [place]="place"></new-post></div>
<div><list-posts [place]="place"></list-posts></div>
...
因此,子组件new-post需要通知子组件列表-post,已经添加了新帖子,并且列表-post应该重新获取与该地点相关的所有帖子。
post_event.dart(事件总线服务)
事件总线服务是在post_new_component和post_list_component之间设置的。
我正在将一个int传递给Stream(int id),这现在并不重要,因为我只需要检查是否触发了一个事件,就可以解析一个字符串,一个对象或其他任何东西,如果您需要随事件发送数据。
@Injectable()
class PostEvent {
final StreamController<int> _onEventStream = new StreamController.broadcast();
Stream<int> onEventStream = null;
static final PostEvent _singleton = new PostEvent._internal();
factory PostEvent() {
return _singleton;
}
PostEvent._internal() {
onEventStream = _onEventStream.stream;
}
onEvent(int id) {
_onEventStream.add(id);
}
}
post_new_component.dart
添加帖子后,将执行_postEvent.onEvent(1)。如上所述,“ 1”并不重要,我只想知道事件是否被触发。
@Component(
selector: 'new-post',
directives: [coreDirectives,
formDirectives,
FileUploader,
materialInputDirectives,
MaterialButtonComponent],
templateUrl: 'post_new_component.html',
styleUrls: ['post_new_component.css'],
providers: [ClassProvider(PostService), ClassProvider(PostEvent)]
)
class PostNewComponent {
final PostService _postService;
final PostEvent _postEvent;
String postText;
Post post;
@Input()
Place place;
PostNewComponent(this._postService, this._postEvent);
// Save a new post
Future<void> save() async {
// Create a new post and then fire a post event to notify the post list component to update itself.
await _postService.create(postText,place.id).then(((_) => _postEvent.onEvent(1)));
}
}
post_list_component.dart
我在组件的构造函数中设置了事件侦听器,该侦听器侦听来自新组件的事件更改。每次收到事件时,我都会通过_getPosts()函数获取所有帖子。
@Component(
selector: 'list-posts',
directives: [coreDirectives, formDirectives],
templateUrl: 'post_list_component.html',
styleUrls: ['post_list_component.css'],
providers: [ClassProvider(PostService), ClassProvider(PostEvent)]
)
class PostListComponent implements OnInit {
final PostService _postService;
final PostEvent _postEvent;
List<Post> posts;
@Input()
Place place;
PostListComponent(this._postService, this._postEvent) {
// listen for postEvents, if received re-fetch posts
_postEvent.onEventStream.listen((int id) => _getPosts());
}
// Get all posts when page loads the first time
void ngOnInit() => _getPosts();
// Function to get all the posts related to a place
Future<void> _getPosts() async {
posts = await _postService.getPostsByPlace(place.id);
}
}
如果有人知道更好的方法,则一定要纠正我,因为我还不熟悉该框架,并且很难理解这些概念。文档涵盖了很多内容,但是如果有人像我这样对框架完全陌生,那么我会丢失一些信息。我们希望对Hero Documentation进行扩展,它涵盖了更复杂的主题,例如子组件之间的通信以及子与父之间的通信,但不确定是否在某处进行了说明,而我只是错过了。