ga-wdi-boston/full-stack-project

[Handlebars] Register Helper - Where to define Handlebars?

Closed this issue ยท 12 comments

I am attempting to use Handlebars register helper to display edit and delete buttons if the data belongs to the current user. Currently, my handlebars is showing the buttons for every comment.

screen shot 2016-10-08 at 9 56 54 am

I am struggling with where to places the Handlebars register helper function and exactly how to define Handlebars. I have tried placing the following code in both the index.js file so it loads on document ready and then in the comments events.js file. I get pretty much the same error message in both cases.

It looks like I am pointing it to the wrong file.

js file:

const Handlebars = require('handlebars');

Handlebars.registerHelper('checkUser', function(comment){
        return comment.user_id === app.user_id;
        });

handlebars template:

  {{#each comments}}
    <div class="comment-module">
      <div class="text-align-left">
        <h4>{{trip.name}}</h4>
        <div class="comment" data-id={{id}}>
          <p class"add-padding">{{user.email}} says:</p>
          <p>"{{comments}}"</p>
        </div>
      </div>
      {{#if checkUser}}
        <button type="click" class:"block" id="delete-comment" data-id={{id}}>X</button>
        <button type="click" class:"block" id="get-single-comment" data-id={{id}}>edit</button>
      {{/if}}
    </div>
  {{/each}}

screen shot 2016-10-08 at 10 06 50 am

@berziii can you help out with this? I meant to ask you about it. Jen is trying to find out where to put her handlebars helper.

Woops. Meant @berziiii. Sorry @berziii

gaand commented

@berziiii The module fs is built into node, so that it's not being found suggests a configuration error or perhaps a circular reference error.

@jenboyd What code invokes the handlebars template that uses the helper?

@gaand, here is my code that invokes the handlebars template. It seems like this code would need to be placed in a new file altogether?

assets/scripts/comments/events.js

const getFormFields = require('../../../lib/get-form-fields');
const api = require('./api');
const ui = require('./ui');

const onGetComments = function (event) {
  event.preventDefault();
  api.getComments(event)
    .done (ui.getCommentsSuccess)
    .fail (ui.failure);
};

const addHandlers = () => {
  $('#my-comments').on('click', onGetComments);
};

assets/scripts/comments/ui.js

const app = require ('../app');
const loadComments = require ('../../templates/comments.handlebars');
const loadSingleComment = require ('../../templates/edit-comment.handlebars');


const getCommentsSuccess = (data) => {
  let allComments = data;
  $('.container').html(loadComments(allComments));
  $('.single-trip-page').hide();
  $('.edit-comment-page').hide();
};
gaand commented

After looking around, this may be a bit more work than you want to tackle (it probably involves changing how webpack loads things).

Luckily, there's another way to make this work. If you look at the example serializer in the rail-api-template, it shows how you can include an ownership boolean in the JSON response. Then your template can just check that boolean.

Please have a look.

Jen, your other option would just be to show an error to the user when they click that button and you get a 422 back. This kind of thing get a whole lot easier with ember!!

gaand commented

Not showing the buttons for an action that cannot be taken is a much better option.

gaand commented

That said, handling errors is always a good idea.

@jenboyd Have you had a chance to look at the example serializer?

I found the code below in the example serializer. I'm thinking I can probably add this to my comments serializer, as well. I would then update my handlebars template to say if editable then display button. I will try it out!

class ExampleSerializer < ActiveModel::Serializer
  attributes :id, :text, :editable

  def editable
    scope == object.user
  end
end

@payne-chris-r @gaand, I added the the editable method to the comments serializer and adjusted the handlebars. Everything is working as expected. Users can no longer see the buttons to edit or delete other users comments. Thanks for your help!

My working code below:

comments serializer

class CommentSerializer < ActiveModel::Serializer
  attributes :id, :comments, :editable
  has_one :user
  has_one :trip

  def editable
    scope == object.user
  end
end

comments.handlebars

  {{#each comments}}
    <div class="comment-module">
      <div class="text-align-left">
        <h4>{{trip.name}}</h4>
        <div class="comment" data-id={{id}}>
          <p class"add-padding">{{user.email}} says:</p>
          <p>"{{comments}}"</p>
        </div>
      </div>
      {{#if editable}}
        <button type="click" class:"block" id="delete-comment" data-id={{id}}>X</button>
        <button type="click" class:"block" id="get-single-comment" data-id={{id}}>edit</button>
      {{/if}}
    </div>
  {{/each}}

Neat solution. I didn't even know that about ExampleSerializer. I'm going to use that trick, too. ๐Ÿ˜„

giphy-10

gaand commented

@jenboyd I'm glad you got it to work. Excellent.