Adding class to html tag not working


#1

Good day everyone! I’m practicing meteor and im currently building a project that everytime i click the <li> tag the background of that singe li should change to yellow. and return back to white colore (default) if i click another li.

here is my code

body.html

<body>
    <h1>Leaderboard</h1>
    {{> leaderboard}}
</body>
<template name="leaderboard">
<ul>
    {{#each player}}
        <li class="player {{selectedClass}}">{{name}}: {{score}}</li>
    {{/each}}
</ul>
</template>

body.js

import {Template} from 'meteor/templating';
import './body.html';
import {PlayersList} from '../api/players.js';
Template.leaderboard.helpers({
        'player': function(){
            return PlayersList.find();
        },
        'selectedClass': function(){
            var playerId = this._id;
            var selectedPlayer = Session.get('selectedPlayer');
            if(playerId == selectedPlayer){
                return "selected"
            }
        }  
    });
Template.leaderboard.events({
    'click .player': function(){
        var playerId = this._id;
        Session.set('selectedPlayer', playerId);
    }
});

main.css

.selected{
	background-color: yellow;
}

#2

Does your .player css class already have background-color property defined?

If so you can try to add the !important tag in your .selected background-color property value (I know it’s ugly, but it’s to see where is the problem)

Also you can try to add some console.log() in the selectedClass helper function to check the differents values


#3

@jdsplit sir. .player dont have css content. the only css code that i did is the .selected. i notice that if i remove the if statement and just return the selected class. all the li tag become yellow. but that’s not the point. I only want to target the clicked li. to turn it to yellow. and go back to original color if i selected another li


#4

Your test prove that the condition if(playerId == selectedPlayer) … in your helper is never true.

Try to add some console.log() and check the content of your selectedPlayer session variable and also the playerId value.

You can then see the values in your browser console and start debugging


#5

you are right sir. i console log inside the if statement. and nothing happens… and when the code run. playerId is undefine. but if i click any li tags. it will return the corresponding unique i.d of it.


#6

Now try to console.log(this) in your helper function to see what this really is.


#7

This is exactly why the Meteor guide now advises against using this in helpers or changing the data context in your templates. It makes it hard to reason about what this is at any point in time.

The recommended way is to be explicit about what you’re working on like so:

body.html

<body>
    <h1>Leaderboard</h1>
    {{> leaderboard}}
</body>
<template name="leaderboard">
<ul>
    <!-- use each...in to preserve data context -->
    {{#each player in players}} 
        <!-- Add `data-id` attr and pass the player into the `selectedClass` helper -->
        <li data-id=player._id class="player {{selectedClass player }}">{{player.name}}: {{player.score}}</li>
    {{/each}}
</ul>
</template>

body.js

import {Template} from 'meteor/templating';
import './body.html';
import {PlayersList} from '../api/players.js';
Template.leaderboard.helpers({
        'players': function(){ // Renamed to plural form for each...in
            return PlayersList.find();
        },
        'selectedClass': function(player){ // Take player as an argument
            var playerId = player._id; // Take id from the player passed as an argument
            var selectedPlayer = Session.get('selectedPlayer');
            if(playerId == selectedPlayer){
                return "selected"
            }
        }  
    });
Template.leaderboard.events({
    'click .player': function(event){
        var playerId = event.currentTarget.dataset.id; // Get id from the element
        Session.set('selectedPlayer', playerId);
    }
});

By making the helpers and events no longer depend on this, and avoid changing the data context (by using each...in instead of each) you’ll have a much better time

I’d also suggest you use a ReactiveDict scoped to the template instead of Session


#8

@coagmano thank you very much for the help! Im making a progress now!


#9

Have a read of this page on the Blaze guide for more awesome tips:

http://blazejs.org/guide/reusable-components.html

The Meteor guides are the best resource I’ve found anywhere