In this step, we will implement the party details view, which is displayed when a user clicks on a party in the parties list. The user will also be able to change the party's details.
To implement the party details view we will use helpers
.
We used helpers
in the previous Component we implemented, but now we will demonstrate how to use it with a single object instead of a Mongo.Collection cursor.
We'll expand the PartyDetails
by using helpers
method, and we will use findOne method from the Mongo.Collection, which returns a single object.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import uiRouter from 'angular-ui-router';
import template from './partyDetails.html';
import { Parties } from '../../../api/parties';
class PartyDetails {
constructor($stateParams, $scope, $reactive) {
'ngInject';
$reactive(this).attach($scope);
this.partyId = $stateParams.partyId;
this.helpers({
party() {
return Parties.findOne({
_id: $stateParams.partyId
});
}
});
}
}
In our example we find our relevant party by its id, and used a regular MongoDB syntax to create our findOne
query, which is explained in Meteor's collection.findOne documentation.
So after declaring this helper, we can just use this.party
in our Component's Controller, or partyDetails.party
in our HTML view.
In partyDetails.html
let's replace the binding to the partyDetails.partyId
with a binding to partyDetails.party.name
and partyDetails.party.description
:
1
2
3
4
5
The party you selected is:
<form>
Party name: <input type="text" ng-model="partyDetails.party.name" />
Description: <input type="text" ng-model="partyDetails.party.description" />
</form>
We used ng-model
and created a form with the party details, now we just missing the "Save" button!
First, let's add a button, and we will use ng-click
with the name of the method that we will later implement:
2
3
4
5
6
7
8
<form>
Party name: <input type="text" ng-model="partyDetails.party.name" />
Description: <input type="text" ng-model="partyDetails.party.description" />
<button ng-click="partyDetails.save()">Save</button>
</form>
<button ui-sref="parties">Back</button>
We also added a "Back" button with uses
ui-sref
attribute, which is a shorthand for creating a link for a state.
And now let's implement the logic of the "Save" button on the controller:
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
}
});
}
save() {
Parties.update({
_id: this.party._id
}, {
$set: {
name: this.party.name,
description: this.party.description
}
});
}
}
const name = 'partyDetails';
We used Parties.update method which is a method that comes from the Mongo.Collection object.
The first parameter is the parties we want to update, in this case, we send the specific party's id, just like we did with findOne
.
In the second parameter we specify the action we want to perform, in our case we used the $set
operator to update the actual relevant fields.
We can also handle success or fail when using Parties.update
by adding a callback as the third argument, for example:
30
31
32
33
34
35
36
37
38
39
40
41
name: this.party.name,
description: this.party.description
}
}, (error) => {
if (error) {
console.log('Oops, unable to update the party...');
} else {
console.log('Done!');
}
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import { name as PartyDetails } from '../partyDetails';
import { Parties } from '../../../../api/parties';
import 'angular-mocks';
describe('PartyDetails', () => {
beforeEach(() => {
window.module(PartyDetails);
});
describe('controller', () => {
let controller;
const party = {
_id: 'partyId',
name: 'Foo',
description: 'Birthday of Foo'
};
beforeEach(() => {
inject(($rootScope, $componentController) => {
controller = $componentController(PartyDetails, {
$scope: $rootScope.$new(true)
});
});
});
describe('save()', () => {
beforeEach(() => {
spyOn(Parties, 'update');
controller.party = party;
controller.save();
});
it('should update a proper party', () => {
expect(Parties.update.calls.mostRecent().args[0]).toEqual({
_id: party._id
});
});
it('should update with proper modifier', () => {
expect(Parties.update.calls.mostRecent().args[1]).toEqual({
$set: {
name: party.name,
description: party.description
}
});
});
});
});
});
We've seen the power of using Meteor.Collection API and how we can get single object from the collections.
We also learned how to update an object with the user's data!
Let's move on to provide some order and structure in our application.