William Melton
William Melton

Reputation: 35

Styling Polymer Element Dynamically

I am trying to make an paper-card element change colors based on the status of the customers data on Fire base, but for some reason the color only updates on the second click of the customer. Right now I have the paper cards ID set to the firebase data in order to make it change colors. Here's my elements style code:

<style is="custom-style">
:host {
  display: block;
}
#cards {
  @apply(--layout-vertical);
  @apply(--center-justified);
}
.row {
  padding: 20px;
  margin-left: 10px;
}
paper-card {
  padding: 20px;
}
#check {
  float: right;
  bottom: 15px;
  --paper-card
}
#Done {
  --paper-card-header: {
    background: var(--paper-green-500);
  };

  --paper-card-content: {
    background: var(--paper-green-300);
  };
}
#Default {
  /*Apply Default Style*/
  /*--paper-card-content: {*/
  /*  background: var(--paper-red-500);*/
  /*};*/
}
paper-icon-button.check{
  color: var(--paper-green-500);
}
paper-icon-button.check:hover{
  background: var(--paper-green-50);
  border-radius: 50%;
}
#check::shadow #ripple {
  color: green;
  opacity: 100%;
}
.iron-selected{
  color: green;
}

And here is the template:

  <template>

<firebase-collection
  location="https://calllistmanager.firebaseio.com/Wilson"
  data="{{wilsonData}}"></firebase-collection>

  <div id="cards">
    <template id="cards" is="dom-repeat" items="{{wilsonData}}" as="customer">
      <paper-card id="{{customer.status}}" class="{{customer.status}}" heading="[[customer.__firebaseKey__]]">
        <div class="card-content">
            <span>Phone: </span><span>[[customer.number]]</span>
            <span>Status: </span><span>[[customer.status]]</span>
            <paper-icon-button style="color: green" id="check" on-tap="checktap" icon="check">
            </paper-icon-button>
          </div>
      </paper-card>
  </template>
  </div>

Here is my script:

<script>

(function() { Polymer({ is: 'list-display',

  properties: {
    wilsonData: {
      type: Object,
      observer: '_dataObserver'
    }
  },

  ready: function() {
      var listRef = new Firebase("https://calllistmanager.firebaseio.com/Wilson");
    },

  checktap: function(e){
    // e.model.customer.status = "Done";
    console.log("Starting Status: " + e.model.customer.status);
    ref = new Firebase("https://calllistmanager.firebaseio.com/Wilson")
    var stat;
    var store = ref.child(e.model.customer.__firebaseKey__);
    store.on("value", function(snapshot){
      stat = snapshot.child("status").val();
    });
    if(stat == "Done"){
      store.update({
        "status": "Default"
      });
      e.model.customer.status = "Default";
    }
    else {
        store.update({
        "status": "Done"
      });
      e.model.customer.status = "Done";
    }
    console.log("Ending Status: " + e.model.customer.status);
    this.updateStyles()
  }
});

})();

at first I thought the problem may be that the function runs updateStyles(); faster than firebase can update but it always works fine on the second click...any suggestions?

Upvotes: 1

Views: 935

Answers (1)

Maria
Maria

Reputation: 5604

I think the problem could be caused by the call to firebase. store.on("value", is not a synchronous function. However, later in your code you assume that you already have a value, that will be set later on whenever the value event fires. You could try adding the rest of your code in the event handler. Like this:

checktap: function(e){
    // e.model.customer.status = "Done";
    console.log("Starting Status: " + e.model.customer.status);
    ref = new Firebase("https://calllistmanager.firebaseio.com/Wilson")
    var store = ref.child(e.model.customer.__firebaseKey__);
    store.once("value", function(snapshot){
        var stat = snapshot.child("status").val();
        if(stat == "Done"){
          store.update({
            "status": "Default"
          });
          e.model.set("customer.status", "Default");
        }
        else {
            store.update({
            "status": "Done"
          });
          e.model.set("customer.status", "Done");
        }
        console.log("Ending Status: " + e.model.customer.status);
        this.updateStyles();
    }.bind(this));
}

Essentially, you wait until the stat variable has been set to do the rest of your tasks. Also note, the bind(this) at the end, which will allow you to update the the styles from the event handler.

Update

There are a couple of more issues. First it's better to uses classes for changing the styles and not IDs. IDs should not change. Then, to bind to the class attribute, use the $ sign. When you update the model, you should use the set API. Have a look at this plunker. It is a small working example (only works in Chrome) that changes styles when you click the checkmark. It does not use Firebase, however.

Here's how you could to the style with classes.

.Done {
  --paper-card-header: {
    background: var(--paper-green-500);
  };

  --paper-card-content: {
    background: var(--paper-green-300);
  };
}

And in your template:

<paper-card class$="{{customer.status}}" heading="[[customer.__firebaseKey__]]">

Upvotes: 2

Related Questions