this is what I am trying to do
My main page has 4 buttons
On click of each button, the modal should open and the content for that section should be at the top. For example, click "All Nutrients" and the modal should open where the content at the top should be the Box that contains NutrientFilterOptions.
My attempt is available at https://codesandbox.io/s/modest-edison-wz8qr?file=/src/App.tsx
What happens now?
When I click on "All Nutrients", modal opens but the Nutrient section is not scrolled to the top.
Note: At this time, the code is only connected using ref for Nutrients.
Any help in educating me how I can achieve my goal is greatly appreciated.
Thank you
I have never seen chakra-ui so please excuse me for not completely solving this problem
I managed to get the desired list to scroll into view with this modification to NutrientFilterOptions.tsx
export const NutrientFilterOptions = () => {
useEffect(() => {
const ele = document.querySelector("#myNutFilter");
if (ele) ele.scrollIntoView();
}, []);
return (
<div id="myNutFilter">
What I am doing is giving the element an id instead of using useRef, although useRef may be ideal in this situation.
I am using useEffect because I want the code to execute after the component renders.
After the component renders I have vanilla js to first check that the element exists (isShown) then I scroll it into view if it does exist.
I would like to add that this does not check how the list was initially shown. You would need a state that keeps track of what opened the options menu, and only scroll if that the source was correct. I would use prop drilling or redux to handle the source of options opening.
hopefully that helps!
Related
I'm a little new to React Native and making an app. There are three components I'm currently concerned with:
AllList.js: A screen comprised of a search bar and a FlatList of RowCard.js instances.
RowCard.js: a custom TouchableHighlight component that displays an item from an API, and currently returns an alert when tapped.
drinkPopup.js: A custom Modal component that needs to take an ID from AllList but be controlled by tapping a RowCard.
I have the list of RowCard instances working, but I need to find a way to make the modal from drinkPopup appear when RowCard is tapped. I'm super confused as to how to approach this, since as far as I know props can only be sent from parent to child.
Any suggestions for how to do this? I've looked around to find answers but the results I've found have just been confusing.
So you need a state that will be accessible by both the drinkPopup and RowCard. The way to go is to keep it in their parent (AllList) and pass it accordingly.
So you Parent should be something like:
const AllList = () => {
const [visibleModalId, setVisibleModalId] = useState(null)
return <>
<RowCard setVisibleModalId={setVisibleModalId}>
<drinkPopup visibleModalId={visibleModalId}>
</>
}
That way you can control the modal from RowCard (by calling setVisibleModalId there) and you also know if the drinkPopup should be visible (because it knows if the visibleModalId is null or not)
I have a component with 3 buttons that trigger their respective tooltip when clicked, as below:
I use state to set the tooltip's ID so that at any time, only ONE tooltip can show. const [visibleTooltip, setVisibleTooltip] = useState(null);
The idea is, the tooltip's visible prop will check against state to return TRUE or FALSE to show that particular tooltip: visible={visibleTooltip === tooltipId}
codesandbox link
What I expect is that when I click button 2, tooltip 2 should show up, closing any other tooltips. However, what happens is that all 3 tooltips show as you click through buttons 1-3.
I suspect the tooltip isn't being re-rendered, but I don't know why. Sticking a key prop onto Tooltip fixes it, but this shouldn't be the solution.
Using latest rc-tooltip 4.2.1 and couldn't find any answers here or in the issues of rc-tooltip's github.
Not sure if missing something really obvious. Thanks!
Currently I'm learning VueJS and I'm working with http://vuematerial.io.
I have build an application with several pages - each of them contains a sidebar (the drawer component https://vuematerial.io/components/drawer).
Since I don't want to copy and paste the same drawer component code over and over again in each page, I just want to create one sidebar component, which I'll then import on each page.
So far, so good.
This is working fine.
But now - I want to be able to open and close the sidebar.
Just before, when the component was directly in the page, it was easy - just a variable assignment with a boolean value to whether show or hide the sidebar.
But now, it seems very hard for me, to synchronize the property over the components.
Let me show you the current new code to clarify what's the problem:
So, this is the page component:
<md-toolbar class="md-primary">
<md-button class="md-icon-button" #click="showSidebar=true">
<md-icon>menu</md-icon>
</md-button><span class="md-title">Dashboard</span>
</md-toolbar>
<Sidebar v-bind:showSidebar="showSidebar"></Sidebar>
So that's the Vue Structure - you can see - I want to bind the showSidebar property.
That's how I'm implementing it within the page
import Sidebar from './sidebar.vue';
export default {
data: function () {
return {
showSidebar: false
}
},
components: {
Sidebar: Sidebar
},
And now the Sidebar component itself:
<md-drawer v-bind:md-active.sync="showSidebar">
The sidebar component then fetches the value over a property like this:
export default {
name: 'sidebar',
props: ['showSidebar'],
And this seems to work!
I can click on the menu button on the page, set the property to true - and the sidebar shows! Great! But.. When I click outside of this sidebar, this warn message appears - and - furthermore - I can't reopen it again on a new click. It closes, but I can't open it again, until I completely reload the page.
How can I be able to solve that?
I have also thinked about using events, since the drawer component seems to listen on events, but I wasn't successful.
That's the current code from the drawer component: https://github.com/vuematerial/vue-material/blob/dev/src/components/MdDrawer/MdDrawer.vue
I hope that it was clear, what my problem is.
I hope, anyone can help me out.
This is my first question here - so please be nice :)
/EDIT:
Opps, here is the warn message:
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "showSidebar"
I'm not a Vue pro - still learning it myself - but I think I can see what is going on here.
I think the warning in particular is because you have a prop AND a data property of the same name. Try removing the data setting. You can change the props setting to this:
props: {
showSidebar: {
type: Boolean,
default: false
}
}
See if that fixes it. Also, given how you seem to be using this, I'd suggest looking into using Vuex. The documentation is good and it could really help manage your app. Possibly even fix that issue with reopening the drawer.
Edit:
After reviewing this user's code more closely (connected with them on discord), I've determined the issue is that while the process of opening the sidebar was managed by a property on the parent component, the act of closing it was strictly occurring in the child. When you have data bound like that from parent to child, you need to be sure to update the source (the parent component) of the relevant changes. In Vue, those changes are only pushed one direction. To pass info up to the parent, you have to $.emit events.
My current recommendation is to add a custom event to the sidebar component tag on the parent component:
<Sidebar v-bind:showSidebar="showSidebar" v-on:hide-sidebar="showSidebar=false"></Sidebar>
And then change the close tag in the child component to this:
<span class="md-title" #click="$emit('hide-sidebar')">FleaMaster</span>
Hopefully this information helps someone else as well!
I am working on a React project with a messaging component nested inside a show component. I am trying to bring the scroll within the messaging component to the last message by using the scrollIntoView javascript function. However, when the function is called, the entire show component page is focused on the message, when I want the page when rendered to start at the top, and just have the last message be the focus only of that component.
I have tried breaking up the components and rendering messaging inside the show component, then calling scrollIntoView there, but that does not work.
Is there a way to bring the scroll only within the component and not the entire page itself? Any hints or direction would be appreciated.
The code for the components are quite long and not that relevant so I can simplify it if needed.
I am using the following function inside the nested messaging component:
scrollLastMessageIntoView() {
const items = document.querySelectorAll('.each-message-box');
const last = items[items.length - 1];
if (last) {
last.scrollIntoView();
}
}
I'm currently building an application using Sencha Touch. We have a certain Carousel on a page that contains multiple items. Upon clicking a button on a different panel, certain items are added and removed to the panel.
The problem: all works as planned for the first click, but clicking upon clicking the same button again, the functionality stops working and the Carousel display turns blank, with none of the items visible.
Below is the handler for the buttons that change the content of the carousel itemsCarousel. The function adds itemPanels[ b.getBadgeText() ] to the itemsCarousel's items. For the first four clicks or so, this works great. After around then, when I click a button, all the items in the Carousel vanish, and I cannot add or remove any more content, even invoking the Carousel manually from the console.
handler: function(b, e) {
itemsCarousel.insert(1, itemPanels[ b.getBadgeText() ]);
itemsCarousel.doLayout(); itemsCarousel.doComponentLayout();
itemsCarousel.setActiveItem(1);
itemsCarousel.remove(0, false);
}
Things I have attempted:
Changing the order by inserting the item at slot 0, setting 0 active, and then removing 1.
Putting javascript breakpoints on each of the lines, seeing where the carousel goes blank. Sometimes it occours at the .insert() statement, sometimes at the .remove().
Doing all this manually, from the console.
Tweaking the autoDestroy parameter in the .remove() call (as seen above) and in the declaration of itemsCarousel.
If you need more code I can post whatever you think may be relevant, I didn't want to pollute this thread with excess code. Thanks for your help!
Edit: If anyone knows another way to reproduce the same functionality, I am open to that as well. I am thinking perhaps creating a dummy holder Container with one item, a carousel, and deleting the entire carousel and re-adding a brand new (with the new items) one upon the button click?
Well, I figured out how to reproduce the functionality using a different method.
I built multiple carousels, each containing the panels I wanted, and then had a root panel that simply sets the active carousel based on button presses. For example, the hierarchy looks like this now:
rootPanel
{
carousel[0]
{
panel1
panel2
}
carousel[1]
{
panel3
panel4
}
...
}
and I perform rootPanel.setActiveItem(x) to display the new carousel.