1

I'm using this code right now, but I'm not really liking the way it looks.

function createPageSettingsPopup(page) {
  return '<div class="form-group">' +
    '<label for="page-title">Title</label>' +
    '<input type="text" class="form-control" id="page-title" value="' + page.title + '">' +
    '</div>'
}

Is there any alternative to write the HTML in strings to make it look better?

GôTô
  • 7,974
  • 3
  • 32
  • 43
Tompina
  • 726
  • 1
  • 9
  • 25

4 Answers4

4

You could use template engines. This is at the expense of elements in the page, but the code will look much cleaner and the template easier to understand as HTML. Put the template in a script tag with type set to text/template

<script type="text/template" id="tmpl">
    <div class="form-group">
        <label for="page-title">Title</label>
        <input type="text" class="form-control" id="page-title" value="{{pageTitle}}">
    </div>
</script>

And modify your function as below. Remember to cache the template.

var template = document.getElementById('tmpl').innerHTML; // cache the HTML
function createPageSettingsPopup(page) {
    // Find an replace the {{pageTitle}} with page.title, and then return the HTML string.
    return template.replace(new RegExp('{{pageTitle}}', 'gi'), page.title) 
}

var template = document.getElementById('tmpl').innerHTML; // cache the HTML
function createPageSettingsPopup(page) {
    // Find an replace the {{pageTitle}} with page.title, and then return the HTML string.
    return template.replace(new RegExp('{{pageTitle}}', 'gi'), page.title) 
}

console.log(
   createPageSettingsPopup({title:'Hello World'})
);
<script type="text/template" id="tmpl">
    <div class="form-group">
        <label for="page-title">Title</label>
        <input type="text" class="form-control" id="page-title" value="{{pageTitle}}">
    </div>
</script>

The above is a minimal example of a template engine, but there are great ones like mustache, handlebars.js, and pug.js

Community
  • 1
  • 1
Adam Azad
  • 11,171
  • 5
  • 29
  • 70
0

Assuming ES6 you can use backticks:

return `<div>
    ...
</div>`;

Or have a look at react, to manipulate your DOM, they use jsx which is really nice:

const element = <h1>Hello, world!</h1>;

In case you are using jQuery, sometimes you can do things like these:

var div = $('div').addClass('form-group');
div.append($('label').attr('for', 'page-title').text('Title');
...

Depending on your problem at hand it might also make sense to have the full html structure written up-front and then just manipulate some content and styling using js. In your example:

$('div#title').show();
$('div#title').find('label.page-title').text('Title');
pintxo
  • 2,085
  • 14
  • 27
  • JSX is about `virtual DOM` which has nothing do to with op's question – pwolaq Jan 17 '17 at 07:57
  • Well, seems to me OP is asking about how to create HTML (manipulate the DOM) using js. I would say react/jsx is pretty good at it (although probably a lot more than what OP is looking for currently. – pintxo Jan 17 '17 at 07:59
0

This does not look better but is another way to create elements in JavaScript

Using the document.createElement you have more programmatic control over which attributes to set

function createPageSettingsPopup(page) {
  var div = document.createElement("div");
  div.className="form-group";
  var label = document.createElement("label");
  label.htmlFor="page-title";
  label.textContent="Title";
  var input = document.createElement("input");
  input.type="text";
  input.className="form-control";
  input.id="page-title";
  input.value=page.title;
  label.appendChild(input);
  div.appendChild(label);
  return div;
}

Same in jQuery:

function createPageSettingsPopup(page) {
  var $div = $("<div />",{"class":"form-group"});
  $div.append(
    $("<label />", {"htmlFor":"page-title").text("Title").append(
      $("<input/>", { "type":"text","class":"form-control","id":"page-title"}).val(page.title)
    )
  );
  return $div;
}
mplungjan
  • 169,008
  • 28
  • 173
  • 236
0

You can try creating a HTML utility that creates elements, add necessary properties and the returns element.

I have created a small implementation of this utility in sample. Benefit of this is you can modify this utility to work with JSON based structure to create dynamic HTML.

Sample

function createPageSettingsPopup(page) {
  var divParams = {
    class: 'form-group'
  }
  var labelParams = {
    for: 'page-title'
  }
  var inputParams = {
    type: 'text',
    class: "form-control",
    id: 'page-title',
    value: page.title
  }

  var div = utils.createMyElement('div', '', divParams);
  var label = utils.createMyElement('label', 'Title', labelParams)
  var input = utils.createMyElement('input', '', inputParams)

  div.appendChild(label);
  div.appendChild(input);

  document.body.appendChild(div)
}

window.addEventListener('load', function() {
  createPageSettingsPopup({
    title: "foo"
  })
})

// This code can be exported to another file
var utils = (function() {
  function createMyElement(type, htmlString, params) {
    var el = document.createElement(type);
    if (htmlString)
      el.innerHTML = htmlString;
    addProps(el, params)
    return el;
  }

  function addProps(el, props, key) {
    if (Object.keys(props).length) {
      for (var k in props) {
        if (typeof(props[k]) === "object") {
          addProps(el, props[k], k);
        } else {
          if (key) {
            el[key][k] = props[k]
          } else {
            el[k] = props[k]
          }
        }
      }
    }
  }

  return {
    createMyElement: createMyElement
  }
})()

You can also try JSON based form.

Sample

JSFiddle

window.addEventListener('load', function() {
  createPageSettingsPopup({
    title: "foo"
  })
})

function createPageSettingsPopup(page) {
  var form = utils.createForm(getFormData(page))
  document.body.appendChild(form)
}

// This can be stored in JSON file or in db and then can be fetched
function getFormData(page) {
  var json = {
    type: "div",
    params: {
      class: 'form-group',
      innerHTML: "",
    },
    children: [{
      type: 'label',
      params: {
        for: 'page-title',
        innerHTML: "Title"
      },
    }, {
      type: 'input',
      params: {
        type: 'text',
        class: "form-control",
        id: 'page-title',
        value: page.title
      }
    }]
  }
  return json
}

// This is a generic utility and can be exported to a utility file
var utils = (function() {
  function JSONBasedForm(form_json) {
    var el = "";
    if (form_json) {
      el = createMyElement(form_json.type, form_json.params);
      if (form_json.children && form_json.children.length > 0) {
        form_json.children.forEach(function(child) {
          var c_el = JSONBasedForm(child)
          c_el && el.appendChild(c_el)
        })
      }
    }
    return el;
  }

  function createMyElement(type, params) {
    var el = document.createElement(type);
    addProps(el, params)
    return el;
  }

  function addProps(el, props, key) {
    if (Object.keys(props).length) {
      for (var k in props) {
        if (typeof(props[k]) === "object") {
          addProps(el, props[k], k);
        } else {
          if (key) {
            el[key][k] = props[k]
          } else {
            el[k] = props[k]
          }
        }
      }
    }
  }

  return {
    createForm: JSONBasedForm
  }
})()
Community
  • 1
  • 1
Rajesh
  • 24,354
  • 5
  • 48
  • 79