2

I am trying to design a calendar component and the html for the section is:

<th id="thNow">July<span class="scrollArrow"><img src="/UpDownArrow.png" /></span>, 2022<span class="scrollArrow"><img src="/UpDownArrow.png" /></span></th>

In JQuery (3 if it matters), the code I'm attempting with it is:

var thNow = $("<th></th>", {    id: "thNow" })
                .html(sMonth)
                .append(
                    $("<span></span>",  {   "class":    "scrollArrow"   })
                        .append(
                            $("<img />",    {   "src":  "/UpDownArrow.png"  })))
                                .html(", ")
                                .html(sYear)
                                .append(
                                    $("<span></span>",  {   "class":    "scrollArrow"   })
                                .append(
                                    $("<img />",    {   "src":  "/UpDownArrow.png"  })));

even though I know that won't work - How do I effectively piece together the string of the Month name like with .html(), an img tag, the text ", " and the year, and another image tag - This Jquery code just replaces the Month name with the year and the image tag.

Do I need to wrap each of the text in a span/div or something? Eventually (after I add the code that is), the month name and year will be links to select a month out of all the months and a year out of all the years like one might see in a date picker but this is more than just a date picker.

It's for my own personal calendar to merge my work and home calendars to make a sort of calendly site for myself but which will use google apis to query my google calendar and Office APIs to query my work calendar and people (or I) can add events to it as well.

Is there a way to do what I want or do I need to definitely wrap each of the text things in a tag of some sort?

1 Answer 1

2

The problem with your code is because you're calling html() to add the , and the year strings. This is overwriting all the previous HTML you appended to the element. Use append() instead.

In addition, the HTML you clone includes an id, as noted by @zer00ne in the comments below. This will mean that your HTML becomes invalid as id attributes must be unique within the DOM. Change this to a class instead.

let sMonth = 'July';
let sYear = '2022';

var thNow = $("<th />", {
    class: "thNow"
  }).html(sMonth)
  .append(
    $("<span />", { class: "scrollArrow" }).append(
      $("<img />", { src: "/UpDownArrow.png" })
    )
  )
  .append(" , " + sYear)
  .append(
    $("<span />", { class: "scrollArrow" }).append(
      $("<img />", { src: "/UpDownArrow.png" })
    )
  );

thNow.appendTo('table tr');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<table>
  <tr>
    <th class="thNow">
      July
      <span class="scrollArrow"><img src="/UpDownArrow.png" /></span> , 2022
      <span class="scrollArrow"><img src="/UpDownArrow.png" /></span>
    </th>
  </tr>
</table>

However it's worth noting that building HTML through JS/jQuery is not an ideal solution. It leads to very verbose code that takes some conscious effort to understand and is difficult to maintain.

The far better approach would be to store the HTML as a template within the HTML page. Then you can just use jQuery to clone that template and update any labels within it.

This pattern has the benefit of separating the HTML and JS concerns (ie. the developer who knows HTML can easily update the template without needing to understand how the JS works), and also allowing for much simpler JS code. Try this:

let addHeader = ($target, month, year) => {
  let html = $('#th-template').html()
    .replace('{{month}}', month)
    .replace('{{year}}', year)
  $target.append(html);
}

$('#add-header').on('click', () => addHeader($('table tr'), 'July', '2022'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<button type="button" id="add-header">Add header</button>

<template id="th-template">
  <th class="thNow">
    {{month}}
    <span class="scrollArrow"><img src="/UpDownArrow.png" /></span> , {{year}}
    <span class="scrollArrow"><img src="/UpDownArrow.png" /></span>
  </th>
</template>

<table>
  <tr>
    <th class="thNow">
      July
      <span class="scrollArrow"><img src="/UpDownArrow.png" /></span> , 2022
      <span class="scrollArrow"><img src="/UpDownArrow.png" /></span>
    </th>
  </tr>
</table>

Sign up to request clarification or add additional context in comments.

6 Comments

Let OP know about dupe ids.
@zer00ne very good point, thanks.
What duplicate ids? There's only 1 id in my example and I'm very careful about not duplicating Ids - Classes are used if an item is used over and over. For example, if I had multiple items of the same functionality - There will only ever be 1 thNow cell in the entire page ever. It's so that I can identify THAT specific header cell to be able to apply a click handler and change CSS later as needed. I can't do it without an Id - it's impossible. This is a component that will only ever be used once per this application. There will be other components of course but totally different Ids
Interesting code but I have no idea how to understand that code - I only know ES5 javascript - never learned ES6 or 7 or typescript of anything else. Plus, right now it's confusing because it's all in one section - when I'm done, I'll be putting it into a class with each sub-component generated by a javascript function/method. So there will be a this.getNowHeader - and so on and so forth. and esp when I do that, I'll be removing all ids and using object references then to apply functions to it. Also - it was my understanding I couldn't use append with text - It was only with like $(...).
I assumed the point of creating the content through JS was to duplicate it multiple times. If not then the id on thNow is fine. it was my understanding I couldn't use append with text - nope, append() works find with text nodes too.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.