JSFiddle - React, Tailwind, and code Playground
HTML
<div id="ew_ability_attributeComponents" data-prototype="<div class="form-group"><label class="control-label required">__name__label__</label><div id="ew_ability_attributeComponents___name__"><div class="form-group"><label class="control-label" for="ew_ability_attributeComponents___name___attribute">ew_ability.attributeComponents.labels.attribute</label><select id="ew_ability_attributeComponents___name___attribute" name="ew_ability[attributeComponents][__name__][attribute]" class="form-control"><option value=""></option><option value="1">Reflexes</option></select></div><div class="form-group"><label class="control-label required" for="ew_ability_attributeComponents___name___composition">ew_ability.attributeComponents.labels.composition</label><div class="input-group"><input type="text" id="ew_ability_attributeComponents___name___composition" name="ew_ability[attributeComponents][__name__][composition]" required="required" class="form-control"><span class="input-group-addon">%</span>
</div></div></div></div>"></div>
JavaScript
$('[data-prototype]').each(function(i, element) {
var prototype = $($(element).data('prototype'));
prototype.find('label[for]').each(function(l, label) {
var input = prototype.find('#' + $(label).attr('for'));
$(label).text(input.attr('name').replace(/__name__/, 'labels').replace(/\[/g, '.').replace(/\]/g, ''));
});
// if you change this to `attr('data-prototype'` it works
$(this).data('prototype', prototype[0].outerHTML);
});
var addAttributeLink = $('<a href="#" class="add-attribute-link">Add an attribute</a>');
var newLinkWrapper = $('<li></li>').append(addAttributeLink);
var addPrototype = function(collection, linkWrapper) {
var prototype = collection.data('prototype');
var index = collection.data('index');
var newForm = prototype.replace(/__name__/g, index);
collection.data('index', ++index);
var formWrapper = $('<li></li>').append(newForm);
newLinkWrapper.before(formWrapper);
};
var attributeCollection = $('#ew_ability_attributeComponents');
attributeCollection.data('index', attributeCollection.find(':input').length);
attributeCollection.append(newLinkWrapper);
addAttributeLink.on('click', function(e) {
e.preventDefault();
addPrototype(attributeCollection, newLinkWrapper);
});