I want to notify a parent component from a child component to update a view in the parent component. I'm using the @Output annotation to do that.
In the parent component the function "loadPosts()" is actually invoked, but the view is not updated. Does anybody know why?
What happens:
- place_component contains a "list-post" directive, which displays all posts.
- place_component contains a modal, to add a new post with a directive "new-post"
- When a new post is saved, a message is parsed back over @output to the "new-post" directive in the modal: (doneIt)="loadPosts()"
- The loadPosts() function is executed, but the "list-post" directive does not reload.
Parent Component:
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>
Child Component
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>
I have now additionally also tried with an EventBus according to this example: 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();}));
}
The behaviour is exactly the same. The loadPosts function is executed, but the view is not loading.