In my component template I'm using AutoDeltaSettings Component which I want to show only If showAuto data attribute's of the component is true.
<auto-delta-settings v-if="showAuto"> </auto-delta-settings>
Here is the showAuto data attribute
data () {
return {
stepWidth: STEP_WIDTH,
headerHeight: HEADER_HEIGHT,
paddingTop: PADDING_TOP,
paddingBottom: PADDING_BOTTOM,
footerHeight: FOOTER_HEIGHT,
showAuto: false
}
}
I have registered the events on the created hook
created () {
EventBus.$on('protocol-changed', this.protocolChanged)
EventBus.$on('show-advanced-settings', this.showAdvancedSettings)
}
When show-advanced-settings event is emitted I'm calling showAdvancedSettings method of the component
methods: {
showAdvancedSettings (toShow) {
console.log("To Show - Before"+ this.showAuto)
this.showAuto = toShow
console.log("To Show - After"+ this.showAuto)
}
}
I'm emitting the event from another component on a click of a button
showAdvancedSettingsModal () {
console.log('Inside advanced settings opener - Before '+ this.showAdvancedSettings)
this.showAdvancedSettings = true
console.log('Inside advanced settings opener - After '+ this.showAdvancedSettings)
EventBus.$emit('show-advanced-settings', this.showAdvancedSettings)
},
But this only works when I click the button first time, in this case AutoDeltaSettings component shows up (which is a basically a modal), when I close the modal and click the button again to display the AutoDeltaSettings component it doesn't work.
I have read this post Conditional v-if is working only for the first time?
Related
I am adding some custom html to a resource timeline if there are no events for that week. It works on initial page load, but when next or prev buttons are clicked, it needs to be initiated again. I have found the proper way to do this in version 6, is to use datesSet.
However, I can't figure out how to call resourceLandDidMount whenever datesSet is fired. Here is the function I need to run with dateSet:
resourceLaneDidMount : function(arg){
if(arg.el.classList.contains('fc-timeline-lane')){
var theElement = arg.el.querySelectorAll('.fc-timeline-lane-frame > .fc-timeline-events')[0]
setTimeout(function(){
if(theElement.querySelectorAll('.fc-timeline-event-harness').length > 0) {
console.log('has event harness class');
} else {
console.log('has no event harness class');
}
})
}
},
Example 1:
click on tab1. Tab 1 is active tab. Click again on tab1(tab1 is active tab) I don't want to call function start() in component 'Details'. Click on tab 2 or tab 3 I want to call function start() in another component 'Details'.
Example 2:
click on tab2. Tab 2 is active tab. Click again on tab2(tab 2 is active tab) I don't want to call function start() in component 'Details'. Click on tab 1 or tab 3 I want to call function start() in another components 'Details'.
Tries to create a condition in the 'Details' component. If the tab is not active, call the start () function. Move the function isActive () and the variable selectedTabId from the component 'Tabs' to 'Details' and call the start function there if the tab is not active. Is my reasoning correct? Is this a good approach?
Code here: https://codepen.io/kaka-milan/pen/oKXJma?editors=1111
Drawing: https://imgur.com/VZ3N5lM
Tabs
var Tabs = React.createClass({
getInitialState: function() {
return { selectedTabId: 1 }
},
isActive: function (id) {
return this.state.selectedTabId === id;
},
setActiveTab: function (selectedTabId) {
this.setState({ selectedTabId });
},
render: function() {
var total = this.props.data.points.total,
tabs = total.map(function (el, i) {
return <Tab
key={ i }
content={ el.name }
id={el.id}
isActive={ this.isActive(el.id) }
onActiveTab={ this.setActiveTab.bind(this, el.id) }
/>
}, this);
return
<div>
<ul className="navigation">
{ tabs }
</ul>
<Details
isActive={ this.isActive}
selectedTabId={this.state.selectedTabId}
/>
</div>
}
});
Details
var Details = React.createClass({
componentDidMount() {
if(!this.props.isActive(this.props.selectedTabId)){
this.start();
}
},
start: function() {
return console.log('aaa')
},
render: function() {
return
<p></p>
}
});
Currently the problem is that Details is rendered when Tabs is rendered so start is only called on first render. Also Details has no way of knowing when state is changed.
One solution is to move start into Tabs and call it in setActiveTab if needed, like below. This allows us to remove the Details component altogether:
var Tabs = React.createClass({
...
setActiveTab: function (selectedTabId) {
if(selectedTabId !==
this.setState({ selectedTabId });
},
start: function () {
console.log('aaa')
},
...
})
Updated codepen: https://codepen.io/sentaipadas/pen/JgYPmq
I haven't worked with react classes for a while, but if you have access to React 16.8 and want to separate state handling logic from rendering (it looks like that is the aim of Details component) you can use React hooks (with classes you could possibly use refs).
Example codepen: https://codepen.io/sentaipadas/pen/mNeboE
I have a Kendo UI Toolbar:
$("#toolbar").kendoToolBar({
items : [ {
type : "button",
text : "List"
} ]
})
and I have a script in my app that will translate strings according to the chosen language; i.e. it will find the word 'List' and change it to 'Liste'.
The problem is with timing. There is a finite time that the Toolbar takes to render, so calling my translation function inside
$(document).ready(function() { })
Is too early.
The Kendo Toolbar component doesn't have an onRendered event handler. Otherwise I could use that.
Is there any way to define an event that occurs after all Kendo components, including Toolbar have been rendered?
First of all: Ain't there a better way to localize your page?
Besides that: I've created a small JavaScript function which waits until a given list of elements exist. Just call it as shown in the comment in $(document).ready(function() { }).
// E.g. waitUntilKendoWidgetsLoaded({ "toolbar": "kendoToolBar" }, doTranslation);
function waitUntilKendoWidgetsLoaded(widgets, action) {
var allLoaded = true;
for (var key in widgets) {
if (widgets.hasOwnProperty(key)) {
allLoaded = allLoaded && $("#" + key).data(widgets[key]) !== undefined;
}
}
if (allLoaded) {
action();
}
else {
setTimeout(waitUntilKendoWidgetsLoaded, 500, widgets, action);
}
}
But be aware: The only thing you know for sure is that the element exists. It does not ensure that the element has finished loading. Especially with Kendo widgets which use a datasource you should use the existing events to trigger your function at the right moment.
All,
I have an Angular2 application. In this application I have a button that opens a dialog. In this dialog is a single div which I need to act on. Is there any way to execute code in a callback after the dialog and all it's children have been created?
The closest I've got is
<modal #openDialog (focusin)="openExplorer('someData')">
...
</modal>
If I go with that approach then my code get's rexecuted if a user clicks on the form fields inside of this div.
// HTML
<p (click)="openTheDialog(openDialog, 'thisDivRightHere')">Click here to open me, fool</p>
<modal #openDialog (focusin)="openExplorer('someData')">
<div id="thisDivRightHere"></div>
</modal>
// Component
openTheDialog(dlg, someDiv) void: {
this.fooBarService.preformTheAction(someDiv);
}
// Service
preformTheAction = function(someDiv) {
$('#' + someDiv).html(new Date());
}
In the above example, without (focusin) then I can't get a handle on "thisDivRightHere"
But if I use (focusin) I can but the date changes every time somethings interacted with.
I solved it by using setTimeout to wait for the element and a carefully placed callback
// HTML
<p (click)="openTheDialog(openDialog)">Click here to open me, fool</p>
<modal #openDialog (onOpen)="openIt(openDialog, 'thisDivRightHere')" >
<div id="thisDivRightHere"></div>
</modal>
tester(someDiv, dialog, callback): void {
var checkExist = setInterval(function() {
if ($('#'+someDiv).length) {
console.log("Exists!");
clearInterval(checkExist);
callback(dialog);
}
}, 100); // check every 100ms
}
// Component
openTheDialog(dlg) {
dlg.open();
}
openIt(dlg, someDiv) void: {
this.tester(someDiv, this.myService, function(dlg) {
dialog.preformTheAction(someDiv);
});
}
// Service
preformTheAction = function(someDiv) {
$('#' + someDiv).html(new Date());
}
I'm trying to learn the basics of facebook's react.js library and I've been lately thinking about a few stuff I can do with it just to get used to the way it works . I'm trying to make a div that contains 2 buttons one is OPEN and the other is CLOSE, when you click the OPEN the react will render a div containing anything (Like a msg saying "You clicked"), this is fine up to now but I cannot figure out how to make it disappear once clicked on the CLOSE button, does anyone know how to do that ? Thanks ^^
There are at least four ways, that depends on the real problem you need to solve:
1) Add #your-div-id.hidden { display:none } styles and add/remove hidden class on click (maybe not React way)
2) Change view state (i.e. opened flag). That's a React way and maybe the simplest choice
onOpen() {
this.setState({ opened: true });
}
onClose() {
this.setState({ opened: false });
}
render() {
var div = (this.state.opened) ? (<div>Your Div Content</div>) : undefined;
return (
//some your view content besides div
{div}
);
}
3) If you use Flux. Move state to Store and subscribe to changes. That maybe useful if you gonna show your div at many parts of your app (i.e. implement error popups which may be shown at any part of an application).
So, first of all let's keep warnings at the store:
var CHANGE_EVENT = 'change';
const warnings = [];
var WarningsStore = assign({}, EventEmitter.prototype, {
getWarnings: () => return warnings,
emitChange: () => this.emit(CHANGE_EVENT),
addChangeListener: callback => this.on(CHANGE_EVENT, callback),
removeChangeListener: callback => this.removeListener(CHANGE_EVENT, callback)
});
WarningsStore.dispatchToken = AppDispatcher.register(action => {
switch(action.type) {
case ActionTypes.ADD_WARNING:
warnings.push(action.warning);
WarningsStore.emitChange();
break;
case ActionTypes.DISMISS_WARNING:
_.remove(warnings, {type: action.warningType}); //that's lodash or underscore method
WarningsStore.emitChange();
break;
}
});
After we have a warnings store, you may subscribe to it from YourView and show popup on each AppDispatcher.dispatch({type: ADD_WARNING, warningType: 'Error'});
var YourView = React.createClass({
componentDidMount: function() {
WarningsStore.addChangeListener(this._onChange);
},
componentWillUnmount: function() {
WarningsStore.removeChangeListener(this._onChange);
},
_onChange() {
this.setState({ warnings: WarningsStore.getWarnings() });
},
render() {
//if we have warnigns - show popup
const warnings = this.state.warnings,
onCloseCallback = () => AppDispatcher.dispatch({type: DISSMISS_WARNING, warningType: warnings[0].warningType});
popup = (warnings.length) ? <YourPopupComponent warning={warnings[0]} onClose={onCloseCallback}> : undefined;
return (
//here the main content of your view
{popup}
);
}
})
4) If you simplified your example, but actually instead of div you need to show/hide another page - you should use react-router
Here's how I would do this:
var foo = React.CreateClass({
getInitialState: function() {
return {
showDiv: false, //Or true if you need it displayed immediately on open
}
},
showIt: function() {
this.setState({showDiv: true});
},
hideIt: function() {
this.setState({showDiv: false});
},
render: function() {
return (<div style={{display: this.state.showDiv ? 'block' : 'none'}}>Your content here</div>);
}
});
What this will do is on state change, the style block of the div will be re-evaluated. If the showDiv state variable is true, it'll display as a block element. Otherwise it'll display none. You could, in theory, do this with CSS as well.
Here's a jsFiddle showing this being done with both CSS classes AND the style attribute on the div element.