2

The below works fine in the LWC playground, but drop it in to the local preview or an org and the css does not behave.

I've discovered that the hover works on a single selector, but with sub selectors it simply doesnt behave correctly.

Here is a playground link (whilst active): https://developer.salesforce.com/docs/component-library/tools/playground/b4msWR4hS/

I've noticed that this works fine on Safari, but not on Chrome. I'm using a Mac with Chrome version Version 80.0.3987.149 (Official Build) (64-bit).

Does anyone have any thoughts on this?

<template>
    <div class="stars" data-stars="1">
      <svg height="25" width="23" class="star" data-rating="1">
        <polygon points="9.9, 1.1, 3.3, 21.78, 19.8, 8.58, 0, 8.58, 16.5, 21.78" style="fill-rule:nonzero;"></polygon>
      </svg>
      <svg height="25" width="23" class="star" data-rating="2">
        <polygon points="9.9, 1.1, 3.3, 21.78, 19.8, 8.58, 0, 8.58, 16.5, 21.78" style="fill-rule:nonzero;"></polygon>
      </svg>
      <svg height="25" width="23" class="star" data-rating="3">
        <polygon points="9.9, 1.1, 3.3, 21.78, 19.8, 8.58, 0, 8.58, 16.5, 21.78" style="fill-rule:nonzero;"></polygon>

      </svg>
      <svg height="25" width="23" class="star" data-rating="4">
        <polygon points="9.9, 1.1, 3.3, 21.78, 19.8, 8.58, 0, 8.58, 16.5, 21.78" style="fill-rule:nonzero;"></polygon>
      </svg>
      <svg height="25" width="23" class="star" data-rating="5">
        <polygon points="9.9, 1.1, 3.3, 21.78, 19.8, 8.58, 0, 8.58, 16.5, 21.78" style="fill-rule:nonzero;"></polygon>
      </svg>
    </div>
</template>
.stars {
  cursor: pointer;
  display: flex;
}
.stars:hover .star polygon {
  fill: #ffd055 !important;
}
.stars .star polygon {
  fill: #d8d8d8;
}
.stars .star:hover ~ .star polygon {
  fill: #d8d8d8 !important;
}
.stars[data-stars] .star polygon {
  fill: #ffd055;
}
.stars[data-stars="1"] .star:nth-child(1) ~ .star polygon {
  fill: #d8d8d8;
}
.stars[data-stars="2"] .star:nth-child(2) ~ .star polygon {
  fill: #d8d8d8;
}
.stars[data-stars="3"] .star:nth-child(3) ~ .star polygon {
  fill: #d8d8d8;
}
.stars[data-stars="4"] .star:nth-child(4) ~ .star polygon {
  fill: #d8d8d8;
}
.stars[data-stars="5"] .star:nth-child(5) ~ .star polygon {
  fill: #d8d8d8;
}
import { LightningElement } from 'lwc';

export default class RatingTest extends LightningElement {


    renderedCallback() {

            var box = this.template.querySelector('.stars');

            Array.prototype.forEach.call(box.getElementsByTagName('svg'), child => {
                child.addEventListener('click', function(e) {
                    let starEl = e.currentTarget;
                    console.log(starEl.parentNode.dataset.stars + ", " + starEl.dataset.rating);
                    this.clickedRating = starEl.dataset.rating;
                    console.log(this.clickedRating);
                    starEl.parentNode.setAttribute('data-stars', starEl.dataset.rating);
                  }.bind(this));
            });

    }
}
  • Can you put the main markup that is causing issues in the question? Your playground link could become invalid, and then this question would not be helpful to anyone else. – Caspar Harmer Mar 29 at 18:16
  • That's great. Also, to make it even better, you could edit the code to that which is the minimum that still causes the issue - ie just two two stars for example. – Caspar Harmer Mar 29 at 18:22
  • 1
    Oh... can you put the playground link back? It's pretty handy :) – Caspar Harmer Mar 29 at 18:26
1

The Problem seems to be in adding onclick on svg during rendered callback instead you can use div above your svg and simly put onlick on itenter image description here

<template>
        <div class="stars" data-stars="1">
          <div class="stardiv"  onclick={clicked} data-rating="1">
          <svg height="25" width="23" class="star" >
            <polygon points="9.9, 1.1, 3.3, 21.78, 19.8, 8.58, 0, 8.58, 16.5, 21.78" style="fill-rule:nonzero;"></polygon>
          </svg>
          </div>
          <div class="stardiv"  onclick={clicked} data-rating="2">
          <svg height="25" width="23" class="star"  >
            <polygon points="9.9, 1.1, 3.3, 21.78, 19.8, 8.58, 0, 8.58, 16.5, 21.78" style="fill-rule:nonzero;"></polygon>
          </svg>
          </div>
          <div class="stardiv"  onclick={clicked} data-rating="3" >
          <svg height="25" width="23" class="star" >
            <polygon points="9.9, 1.1, 3.3, 21.78, 19.8, 8.58, 0, 8.58, 16.5, 21.78" style="fill-rule:nonzero;"></polygon>

          </svg>
          </div>
          <div class="stardiv"  onclick={clicked} data-rating="4" >
          <svg height="25" width="23" class="star" >
            <polygon points="9.9, 1.1, 3.3, 21.78, 19.8, 8.58, 0, 8.58, 16.5, 21.78" style="fill-rule:nonzero;"></polygon>
          </svg>
          </div>
          <div class="stardiv"  onclick={clicked} data-rating="5">
          <svg height="25" width="23" class="star"  >
            <polygon points="9.9, 1.1, 3.3, 21.78, 19.8, 8.58, 0, 8.58, 16.5, 21.78" style="fill-rule:nonzero;"></polygon>
          </svg>
          </div>
        </div>
    </template>

and also change css a bit

.stars {
    cursor: pointer;
    display: flex;
  }
  .stars:hover .stardiv .star polygon {
    fill: #ffd055 !important;
  }
  .stars .stardiv .star polygon {
    fill: #d8d8d8;
  }
  .stars .stardiv:hover ~.stardiv .star polygon {
    fill: #d8d8d8 !important;
  }
  .stars[data-stars] .stardiv .star polygon {
    fill: #ffd055;
  }
  .stars[data-stars="1"] .stardiv:nth-child(1)~ .stardiv .star polygon {
    fill: #d8d8d8;
  }
  .stars[data-stars="2"] .stardiv:nth-child(2)~ .stardiv .star polygon {
    fill: #d8d8d8;
  }
  .stars[data-stars="3"] .stardiv:nth-child(3)~ .stardiv .star polygon {
    fill: #d8d8d8;
  }
  .stars[data-stars="4"] .stardiv:nth-child(4)~ .stardiv .star polygon{
    fill: #d8d8d8;
  }
  .stars[data-stars="5"] .stardiv:nth-child(5)~ .stardiv .star polygon {
    fill: #d8d8d8;
  }

JS

import { LightningElement } from 'lwc';

export default class RatingTest extends LightningElement {



    clicked(e){
        let starEl = e.currentTarget;
                    console.log(starEl.parentNode.dataset.stars + ", " + starEl.dataset.rating);
                    this.clickedRating = starEl.dataset.rating;
                    console.log(this.clickedRating);
                    starEl.parentNode.setAttribute('data-stars', starEl.dataset.rating);

    }
}
| improve this answer | |
  • So I've just copied this in to my code and trying in local preview it makes no difference, I'm using Chrome BTW. I've noticed that in Safari it seems to work fine. – Skynet5 Mar 29 at 18:05
  • @Skynet5 strange it works for me on chrome – User6670 Mar 29 at 18:09
  • does the hovering work, so you can hover over the 3rd star and starts 1-3 light up? I'm in chrome 80. I've also noticed that if I enter developer mode in chrome after I've clicked on one the css takes effect. – Skynet5 Mar 29 at 18:13
  • yes hovering is working and the chrome is Version 80.0.3987.132 (Official Build) (64-bit) – User6670 Mar 29 at 18:18
  • are you on mac? My version is Version 80.0.3987.149. – Skynet5 Mar 29 at 18:24
0

Fixed!

Salesforce does not assign the shadowselector name consistently in the DOM. It uses the the component name to add an attribute to all elements, but isnt consistent in the capitalisation of these across the elements. It takes the component name and toLowers some parts of the name. Chrome expects a case match to the css selectors for them to activate.

Two components: myRating and rating: same code, just the case different, and the first one doesn't work in Chrome, but the other does.

For others to see, go to the playground above and change app to myApp and then the CSS stops working.

Basically, you need to ensure your component name is all lowercase.

| improve this answer | |
  • Can you elaborate more on what were changes you had done for fix. It is not quite clear. – devforce Mar 30 at 11:19
  • added some clarity – Skynet5 Mar 30 at 12:02
  • @Skynet5 are you saying the code that you pasted in your question will start working if we create a LWC with lowercase letters? – User6670 Mar 30 at 13:20
  • Certainly the CSS start to behave. The reason it worked in the playground was because the default component is called app, all lower case. I took your advice on the way I was attaching the onclick. That was left over from originally dynamically adding in element (lwc dom manual) however so likely it wouldnt have been left like that. – Skynet5 Mar 30 at 13:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.