I want to use Foundation's reveal plugin to display a nice modal in a Cycle.js app.
After playing with Webpack and it's configuration for hours, I figured how to propertly import foundation's js into my (es6) app.
However, since I'm dealing with virtual dom, the actual html does not exist when foundation's js is initialized.
Here's my component's code:
import Rx from 'rx';
import {div} from '@cycle/dom';
import $ from 'jquery';
import {foundation} from 'foundation-sites/js/foundation.core';
import 'foundation-sites/js/foundation.util.keyboard';
import 'foundation-sites/js/foundation.util.box';
import 'foundation-sites/js/foundation.util.triggers';
import 'foundation-sites/js/foundation.util.mediaQuery';
import 'foundation-sites/js/foundation.util.motion';
import 'foundation-sites/js/foundation.reveal';
require('./styles/configuration-modal.scss');
function ConfigurationModal(sources) {
const values$ = sources.props$;
const vtree$ = Rx.Observable.just(1).map(() => {
return div(
'#config-modal.reveal',
{attributes: {
'data-reveal': ''
}},
['hello']
);
});
return {
DOM: vtree$,
values$
};
}
$(function() {
$.fn.foundation = foundation;
$(document).foundation();
});
export default ConfigurationModal;
My main.js:
import Rx from 'rx';
import Cycle from '@cycle/core';
import {makeDOMDriver, div} from '@cycle/dom';
import ConfigurationModal from './components/ConfigurationModal/index';
require('./styles/index.scss');
function main(sources) {
const props$ = Rx.Observable.of({
pomodoroDuration: 25 * 60,
shortBreakDuration: 5 * 60,
longBreakDuration: 15 * 60
});
const configurationModal = ConfigurationModal({
DOM: sources.DOM,
props$
});
return {
DOM: configurationModal.DOM,
};
}
Cycle.run(main, {
DOM: makeDOMDriver('#app')
});
Now, if I run $(document).foundation()
in the console once the app is initialized, things work as expected. But in the app code, since the dom is virtual and the actual html has not yet been injected, nothing appears.
How could I run js code after the app was fully initialized and the dom actually populated?
In Cycle, there's a useful feature of the DOM driver that allows you to subscribe to updates for elements.
In this case, you can run code after the app starts up like this:
DOM
.select(':root')
.element()
.take(1)
.subscribe((element) => $(document).foundation())
You could add that to your main, and that should solve your problem.
However, in Cycle it's idomatic to encapsulate all of your subscribes in drivers, as they're usually side effects. In this case, you can make a driver to start Foundation, like so:
function startFoundation () {
$(document).foundation();
}
function foundationDriver(sink$) {
return sink$.take(1).subscribe(startFoundation);
}
And in your main.js:
function main(sources) {
// ...
const startup$ = sources.DOM.select(':root').element().take(1);
return {
DOM: configurationModal.DOM,
FoundationStartup: startup$
};
}
Cycle.run(main, {
DOM: makeDOMDriver('#app'),
FoundationStartup: foundationDriver
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With