Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@andrewk
Last active August 29, 2015 13:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save andrewk/10867419 to your computer and use it in GitHub Desktop.
Save andrewk/10867419 to your computer and use it in GitHub Desktop.
Response to request for modelling nested DOM as flight components - https://gist.github.com/djreimer/10687904
'use strict';
define(
[
'flight/lib/component'
],
function(defineComponent) {
return defineComponent(ConditionSet);
function ConditionSet() {
this.defaultAttrs({
'childTemplate' : 'Override this',
'conditionList' : '.conditions',
'addCondition' : '.js-add-condition',
'removeSelf' : '.js-remove-self'
});
this.after('initialize', function() {
this.on('click', { 'addCondition' : this.appendNewCondition});
this.on('click', { 'removeSelf' : this.removeSelf});
});
this.appendNewConditionSet(e, data) {
e.preventDefault();
// probably pre-populate the template using Mustache, underscore, etc
this.select('conditionList').append(this.childTemplate);
this.trigger('uiAddCondition', { foo : bar});
};
this.removeSelf(e, data) {
e.preventDefault();
this.$node.remove();
this.trigger('uiRemoveConditionSet', { foo : bar});
};
}
}
);
'use strict';
define(
[
'flight/lib/component'
],
function(defineComponent) {
return defineComponent(ConditionSet);
function ConditionSet() {
this.defaultAttrs({
'childTemplate' : 'Override this',
'conditionList' : '.conditions',
'addCondition' : '.js-add-condition',
'removeSelf' : '.js-remove-self'
});
this.after('initialize', function() {
this.on('click', { 'addCondition' : this.appendNewCondition});
this.on('click', { 'removeSelf' : this.removeSelf});
});
this.appendNewConditionSet(e, data) {
e.preventDefault();
// probably pre-populate the template using Mustache, underscore, etc
this.select('conditionList').append(this.childTemplate);
this.trigger('uiAddCondition', { foo : bar});
};
this.removeSelf(e, data) {
e.preventDefault();
this.$node.remove();
this.trigger('uiRemoveConditionSet', { foo : bar});
};
}
}
);
- I wrote this on the train after a long day with a heavy head cold. I haven't run it,
but regardless of likely errors I think it expresses the design well enough.
- Segment and ConditionSet look close to identical, but that's likely due to the simplified
nature of the outline you provided
- I don't like attaching components to classes unless they're `js-`, as it's coupling
your styling and behaviour layers. We excelusively use data attributes for JS-DOM coupling
and I've quickly grown fond of the approach.
- The components could easily listen for add and remove events from their children,
their grandchildren etc.
- I don't know what JS background you're coming from, but in something like Backbone the
intention would be to model the data structure and then hang Views off that data structure.
It can be hard to get out of that at first, but if you strive to only model the
interaction/interface layer, you can keep your Model out of your javascript.
- I wrote an article on flight last week that goes into more details if you're interested:
http://www.sitepoint.com/taking-flight-twitter-flight/
cheers,
Andrew
<script type="text/html" id="tpl-segment">
<div class="segment" data-segment>
<ul class="condition-sets"></ul>
<a href="#" class="js-add-conditionset">Add condition set</a>
<a href="#" class="js-remove-self">Remove this segment</a>
</div>
</script>
<script type="text/html" id="tpl-conditionset">
<li class="condition-set">
<ul class="conditions"></ul>
<a href="#" class="js-add-condition">Add condition</a>
<a href="#" class="js-remove-self">Remove this condition set</a>
</li>
</script>
<script type="text/html" id="tpl-condition">
<li class="condition">
<input type="text" name="{{ name }}" value="{{ value }}" />
<a href="#" class="js-remove-self">Remove this condition set</a>
</li>
</script>
'use strict';
require(
[
'segment',
'condition-set',
'condition',
],
function (
Segment,
ConditionSet,
Condition
) {
$(function() {
Segment.attachTo('.segment', { childTemplate : $('#tpl-conditionset').html() });
ConditionSet.attachTo('.condition-set', { childTemplate : $('#tpl-condition').html() });
ConditionSet.attachTo('.condition');
});
}
);
'use strict';
define(
[
'flight/lib/component'
],
function(defineComponent) {
return defineComponent(Segment);
function Segment() {
this.defaultAttrs({
'childTemplate' : 'Override this',
'conditionSetList' : '.condition-sets',
'addConditionSet' : '.js-add-conditionset',
'removeSelf' : '.js-remove-self'
});
this.after('initialize', function() {
this.on('click', { 'addConditionSet' : this.appendNewConditionSet});
});
this.appendNewConditionSet(e, data) {
e.preventDefault();
// probably pre-populate the template using Mustache, underscore, etc
this.select('conditionSetList').append(this.childTemplate);
this.trigger('uiAddConditionSet', { foo : bar});
}
this.removeSelf(e, data) {
e.preventDefault();
this.$node.remove();
this.trigger('uiRemoveSegment', { foo : bar});
};
}
}
);
@derrickreimer
Copy link

Awesome, really appreciate you taking the time to write this.

When you call .attachTo, does it automatically bind to all future DOM nodes with that selector?

e.g. if there are no .condition-set nodes on the DOM when this is called, does it do anything?

ConditionSet.attachTo('.condition-set', { childTemplate : $('#tpl-condition').html() });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment