Angular 1 has great and very simple directives that help us show and hide DOM elements conditionally. You can bind them to an expression, variables or functions.
First, let's learn about ng-show and ng-hide.
So one thing we want to hide and show is the form for creating a new party. If a user is not logged in, they can't create a party, so why displaying the form for them? If the user is not logged in, we want to display a message saying they need to log in to create a new party.
In PartiesList
add a ng-show
directive to the PartyAdd like that:
1
2
3
4
<party-add ng-show="partiesList.isLoggedIn"></party-add>
<input type="search" ng-model="partiesList.searchText" placeholder="Search" />
Now, we need to add the ability to detect if there is a user logged in at the moment, so let's add a helper for that:
45
46
47
48
49
50
51
52
53
},
partiesCount() {
return Counts.get('numberOfParties');
},
isLoggedIn() {
return !!Meteor.userId();
}
});
}
Then right after the form, add this HTML:
1
2
3
4
5
6
7
<party-add ng-show="partiesList.isLoggedIn"></party-add>
<div ng-hide="partiesList.isLoggedIn">
Log in to create a party!
</div>
<input type="search" ng-model="partiesList.searchText" placeholder="Search" />
That is exactly the opposite - if isLoggedIn
is true or we're in the processing of logging in, hide that div.
Now add the same to the PartyRsvp:
14
15
16
17
18
19
20
</a>
<p>{{party.description}}</p>
<party-remove party="party"></party-remove>
<party-rsvp party="party" ng-show="partiesList.isLoggedIn"></party-rsvp>
<party-rsvps-list rsvps="party.rsvps"></party-rsvps-list>
<party-unanswered party="party"></party-unanswered>
<party-creator party="party"></party-creator>
Add let's add this after the RSVP buttons:
15
16
17
18
19
20
21
22
23
24
<p>{{party.description}}</p>
<party-remove party="party"></party-remove>
<party-rsvp party="party" ng-show="partiesList.isLoggedIn"></party-rsvp>
<div ng-hide="partiesList.isLoggedIn">
<i>Sign in to RSVP for this party.</i>
</div>
<party-rsvps-list rsvps="party.rsvps"></party-rsvps-list>
<party-unanswered party="party"></party-unanswered>
<party-creator party="party"></party-creator>
Next thing we want to hide is the 'delete party' option, in case the logged-in user is not the party's owner.
Lets add ng-show to the delete button like that:
13
14
15
16
17
18
19
20
21
22
23
24
{{party.name}}
</a>
<p>{{party.description}}</p>
<party-remove party="party" ng-show="partiesList.isOwner(party)"></party-remove>
<party-rsvp party="party" ng-show="partiesList.isLoggedIn"></party-rsvp>
<div ng-hide="partiesList.isLoggedIn">
<i>Sign in to RSVP for this party.</i>
</div>
<party-rsvps-list rsvps="party.rsvps"></party-rsvps-list>
<party-unanswered party="party"></party-unanswered>
<party-creator party="party"></party-creator>
In here you can see that ng-show
can get a statement, in our case - the user exists (logged in) and is also the party's owner.
But we just missing the helper we used:
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
},
isLoggedIn() {
return !!Meteor.userId();
},
currentUserId() {
return Meteor.userId();
}
});
}
isOwner(party) {
return this.isLoggedIn && party.owner === this.currentUserId;
}
pageChanged(newPage) {
this.page = newPage;
}
ng-if acts almost the same as ng-show
but the difference between them
is that ng-show
hides the element by changing the display css property and ng-if
simply removes it from the DOM completely.
So let's use ng-if
to hide the outstanding invitations from a party, if the party is public (everyone is invited!):
20
21
22
23
24
25
26
27
28
29
30
31
</div>
<party-rsvps-list rsvps="party.rsvps"></party-rsvps-list>
<party-unanswered party="party" ng-if="!party.public"></party-unanswered>
<div ng-if="party.public">
Everyone is invited
</div>
<party-creator party="party"></party-creator>
</li>
</ul>
Now lets hide the 'PartyUninvited' inside PartyDetails
in case the user is not logged in or can't invite to the party:
To do that we will create a scope function that returns a boolean and associate it with ng-show
:
Create a new function inside partyDetails
component, called canInvite
:
31
32
33
34
35
36
37
38
39
40
41
42
43
44
});
}
canInvite() {
if (!this.party) {
return false;
}
return !this.party.public && this.party.owner === Meteor.userId();
}
save() {
Parties.update({
_id: this.party._id
and add the ng-show
to the PartyUninvited
:
8
9
10
11
<button ui-sref="parties">Back</button>
<party-uninvited party="partyDetails.party" ng-show="partyDetails.canInvite()"></party-uninvited>
Let's add a li
that tells the user that everyone is already invited, if that is the case
4
5
6
7
8
9
10
<div>{{ user | displayNameFilter }}</div>
<button ng-click="partyUninvited.invite(user)">Invite</button>
</li>
<li ng-if="(partyUninvited.users | uninvitedFilter:partyUninvited.party).length <= 0">
Everyone are already invited.
</li>
</ul>
Here, we are taking the result of the uninvited users and checking for its length.
But we are just missing the helpers in this component, so let's add it here as well:
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
},
users() {
return Meteor.users.find({});
},
isLoggedIn() {
return !!Meteor.userId();
},
isOwner() {
if (!this.party) {
return false;
}
return this.party.owner === Meteor.userId();
}
});
}
Now lets disable the PartyDetails
input fields in case the user doesn't have permission to change them (currently, the server is stopping the user, but there is no visual feedback aside from the server overriding the local edit immediately after):
1
2
3
4
5
6
7
8
The party you selected is:
<form>
Party name: <input type="text" ng-model="partyDetails.party.name" ng-disabled="!partyDetails.isOwner"/>
Description: <input type="text" ng-model="partyDetails.party.description" ng-disabled="!partyDetails.isOwner"/>
Public Party? <input type="checkbox" ng-model="partyDetails.party.public" ng-disabled="!partyDetails.isOwner"/>
<button ng-click="partyDetails.save()">Save</button>
</form>
So now our example looks much better after we hide things based on the current situation.
In the next chapters we will add Google Maps and some CSS and styling to our app.