I can't close or hide my vue-dialog and I don't know why. This is my js file from which I call the dialog:
<ItemChooserDialog v-model="showItemChooser" #onItemSelected="onStockSelected" />
export default {
data() {
return {
showItemChooser: false,
}
}),
methods: {
chooseItem(context) {
var self = this;
self.showItemChooser = true;
},
onStockSelected(result) {
var self = this;
let id = result.id;
let name = result.name;
self.showItemChooser = false;
},
}
and this is my Dialog:
<template>
<v-dialog v-model="show" max-width="600">
...
</v-dialog>
</template>
computed: {
show: {
get () {
return this.value
},
set (value) {
this.$emit('input', value)
}
}
},
props: {
value: Boolean
},
methods: {
rowClick{
this.$emit('onItemSelected', clicked_item);
}
}
If I choose an item in the dialog the callback-method "onStockSelected" of the js file runs and self.showItemChooser is set to false but the dialog is still visible.
You don't have any code that actually hides the dialog. The most common way to conditionally hide/show an element is to use the v-if directive.
On your dialog element:
<template>
<v-dialog v-if="value" v-model="show" max-width="600">
...
</v-dialog>
</template>
Check this codesandbox I made: https://codesandbox.io/s/stack-70146776-6tczf?file=/src/components/ItemChooserDialog.vue
I can see you may took as example one of my previous answers. In this case, since you're using the prop value of your custom dialog component to handle the v-dialog v-model. You can close the dialog in two ways.
Closing the dialog from the parent component by setting up your showItemChooser to false. As you're doing on your example. Which I think it's not working because you declared your rowClick method without parentheses in your child component.
Also on my example I decided to use kebab-case on my event name but that just a convention from eslint. Everything else looks alright.
onStockSelected(result) {
var self = this;
let id = result.id;
let name = result.name;
self.showItemChooser = false;
},
Closing the dialog from the child component. Since you're using the computer property show on the v-model of your v-dialog. You can close the dialog by simply setting the show value to false.
closeFromChild() {
this.show = false
}
Last but not least, v-dialog's by default close themselves if you click outside the dialog. If you want to avoid this functionality you can set the persistent prop to your dialog as I did on my example.
Related
I'm trying to make a Kendo dialog pop-up. But i need to hide a button under a certain condition. Can i make an if statement somewhere in actions property or is there any other way to hide them from outside?
I know that you can do whatever in content property, but i was wondering if i can customize existing buttons. This is how i theoretically imagined it but it didn't work
actions: [{
if(link !=null) {
text: linkName,
action: function (e) {
window.location = link;
return true;
},
}
}, {
text: 'Закрыть',
action: function (e) {
Close();
return true;
}
}]
As briosheje said, you have to define array before rendering the widget, but you can update existing dialog's actions with setOptions method. You can check a basic example at https://dojo.telerik.com/EJefarON/8
i'm trying to implement a text selection listener to display a toolbar for some custom options
<script>
export default {
name: "home",
created() {
document.onselectionchange = function() {
this.showMenu();
};
},
data() {
return {
...
};
},
methods: {
showMenu() {
console.log("show menu");
}
}
</script>
<style scoped>
</style>
but it still display that can't call showMenu of undefined, so i tried in this way:
created() {
vm = this;
document.onselectionchange = function() {
vm.showMenu();
};
},
so, nothing changed =(
i need to use this selectionchange because its the only listener that i can add that will handle desktop and mobile together, other method i should implement a touchup, touchdown and its not working for devices
Functions declared the classic way do have their own this. You can fix that by either explicitly binding this using Function.prototype.bind() or by using an ES6 arrow function (which does not have an own this, preserving the outer one).
The second problem is that if you have more than one of those components you've shown, each will re-assign (and thus, overwrite) the listener if you attach it using the assignment document.onselectionchange =. This would result in only the last select element working as you expect because it's the last one assigned.
To fix that, I suggest you use addEventListener() instead:
document.addEventListener('selectionchange', function() {
this.showMenu();
}.bind(this));
or
document.addEventListener('selectionchange', () => {
this.showMenu();
});
A third solution stores a reference to this and uses that in a closure:
const self = this;
document.addEventListener('selectionchange', function() {
self.showMenu();
});
I have a link in a React component:
<a href="#goals-tab" className={ this.setTabStyle()}>Goals</a>
Now, inside setTabStyle method, can I access attributes of the a element, like href without explicitly passing it to the method as a parameter?
If you use a ref, then your component renders DOM without the styles, and then applies the new styles. So the user will notice the change of styles.
I would advise to pass link as a parameter to setTabStyle(link), or make the link another prop of your component:
var Component = React.createClass({
handleClick: function (e) {
console.log(e.currentTarget.getAttribute('href'));
},
setTabStyle: function () {
if (this.props.link == this.props.activelink) {
return myActiveLinkStyle
} else {
return myInactiveLinkStyle
}
},
render: function() {
return <a href={this.props.link} style={this.setTabStyle()} onClick={this.handleClick}>Click</a>;
}
});
That way, you get the right style from the initial load..
Here's a js fiddle showing the question in action.
In the render function of a component, I render a div with a class .blah. In the componentDidMount function of the same component, I was expecting to be able to select the class .blah and append to it like this (since the component had mounted)
$('.blah').append("<h2>Appended to Blah</h2>");
However, the appended content does not show up. I also tried (shown also in the fiddle) to append in the same way but from a parent component into a subcomponent, with the same result, and also from the subcomponent into the space of the parent component with the same result. My logic for attempting the latter was that one could be more sure that the dom element had been rendered.
At the same time, I was able (in the componentDidMount function) to getDOMNode and append to that
var domnode = this.getDOMNode();
$(domnode).append("<h2>Yeah!</h2>")
yet reasons to do with CSS styling I wished to be able to append to a div with a class that I know. Also, since according to the docs getDOMNode is deprecated, and it's not possible to use the replacement to getDOMNode to do the same thing
var reactfindDomNode = React.findDOMNode();
$(reactfindDomNode).append("<h2>doesn't work :(</h2>");
I don't think getDOMNode or findDOMNode is the correct way to do what I'm trying to do.
Question: Is it possible to append to a specific id or class in React? What approach should I use to accomplish what I'm trying to do (getDOMNode even though it's deprecated?)
var Hello = React.createClass({
componentDidMount: function(){
$('.blah').append("<h2>Appended to Blah</h2>");
$('.pokey').append("<h2>Can I append into sub component?</h2>");
var domnode = this.getDOMNode();
$(domnode).append("<h2>appended to domnode but it's actually deprecated so what do I use instead?</h2>")
var reactfindDomNode = React.findDOMNode();
$(reactfindDomNode).append("<h2>can't append to reactfindDomNode</h2>");
},
render: function() {
return (
<div class='blah'>Hi, why is the h2 not being appended here?
<SubComponent/>
</div>
)
}
});
var SubComponent = React.createClass({
componentDidMount: function(){
$('.blah').append("<h2>append to div in parent?</h2>");
},
render: function(){
return(
<div class='pokey'> Hi from Pokey, the h2 from Parent component is not appended here either?
</div>
)
}
})
React.render(<Hello name="World" />, document.getElementById('container'));
In JSX, you have to use className, not class. The console should show a warning about this.
Fixed example: https://jsfiddle.net/69z2wepo/9974/
You are using React.findDOMNode incorrectly. You have to pass a React component to it, e.g.
var node = React.findDOMNode(this);
would return the DOM node of the component itself.
However, as already mentioned, you really should avoid mutating the DOM outside React. The whole point is to describe the UI once based on the state and the props of the component. Then change the state or props to rerender the component.
Avoid using jQuery inside react, as it becomes a bit of an antipattern. I do use it a bit myself, but only for lookups/reads that are too complicated or near impossible with just react components.
Anyways, to solve your problem, can just leverage a state object:
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="https://fb.me/react-0.13.3.js"></script>
</head>
<body>
<div id='container'></div>
<script>
'use strict';
var Hello = React.createClass({
displayName: 'Hello',
componentDidMount: function componentDidMount() {
this.setState({
blah: ['Append to blah'],
pokey: ['pokey from parent']
});
},
getInitialState: function () {
return {
blah: [],
pokey: []
};
},
appendBlah: function appendBlah(blah) {
var blahs = this.state.blah;
blahs.push(blah);
this.setState({ blah: blahs });
},
render: function render() {
var blahs = this.state.blah.map(function (b) {
return '<h2>' + b + '</h2>';
}).join('');
return React.createElement(
'div',
{ 'class': 'blah' },
{ blahs: blahs },
React.createElement(SubComponent, { pokeys: this.state.pokey, parent: this })
);
}
});
var SubComponent = React.createClass({
displayName: 'SubComponent',
componentDidMount: function componentDidMount() {
this.props.parent.appendBlah('append to div in parent?');
},
render: function render() {
var pokeys = this.props.pokeys.map(function (p) {
return '<h2>' + p + '</h2>';
}).join('');
return React.createElement(
'div',
{ 'class': 'pokey' },
{ pokeys: pokeys }
);
}
});
React.render(React.createElement(Hello, { name: 'World' }), document.getElementById('container'));
</script>
</body>
</html>
Sorry for JSX conversion, but was just easier for me to test without setting up grunt :).
Anyways, what i'm doing is leveraging the state property. When you call setState, render() is invoked again. I then leverage props to pass data down to the sub component.
Here's a version of your JSFiddle with the fewest changes I could make: JSFiddle
agmcleod's advice is right -- avoid JQuery. I would add, avoid JQuery thinking, which took me a while to figure out. In React, the render method should render what you want to see based on the state of the component. Don't manipulate the DOM after the fact, manipulate the state. When you change the state, the component will be re-rendered and you'll see the change.
Set the initial state (we haven't appended anything).
getInitialState: function () {
return {
appended: false
};
},
Change the state (we want to append)
componentDidMount: function () {
this.setState({
appended: true
});
// ...
}
Now the render function can show the extra text or not based on the state:
render: function () {
if (this.state.appended) {
appendedH2 = <h2>Appended to Blah</h2>;
} else {
appendedH2 = "";
}
return (
<div class='blah'>Hi, why isn't the h2 being appended here? {appendedH2}
<SubComponent appended={true}/> </div>
)
}
I just want to know the best way to proceed (don´t need the code, just the way to do it). I´m trying to show a dropdown menu when I click on it´s LI element.
var Balloon = React.createClass({displayName: "Balloon",
getInitialState: function() {
return { shaded: false };
},
handleClick: function(event) {
this.setState({ shaded: !this.state.shaded });
},
render: function() {
var panel = this.state.shaded ? React.createElement(BalloonPanel, {type: this.props.type, data: this.props.data}) : "";
return (
React.createElement("li", {onClick: this.handleClick},
React.createElement("a", {href: ""}),
React.createElement("div", {hidden: true}),
React.createElement("div", null,
React.createElement("div", {class: "triangle"}, " "),
panel
)
)
);
}
});
Here is the complete code:
Thanks in advance.
So assuming your drop downs are all reliant upon one another, i.e.. when you click one the others close etc... than they should all be built with the same object and ascribe to a click event that passes this to the parent.
var ParentComponent = React.createClass({
clicked: function () {
alert("you clicked me");
},
return: function () {
render (
<ReactListChild onClick={this.props.clicked.bind(this)} />
)
});
Keep in mind you need to use the bind method in order for the children to know which one was clicked (to take the appropriate action)
So summing this up, your parent component should have a state variable saying which one to show and set some sort of variable, possibly give it the name of the element or something. that way if that element is not listed as shown in state the others will remain closed.
fyi, I did not test this code, it's just a rough idea. Most likely you will do some sort of for loop to render many of these child elements. Remember the bind, or you'll get burned.