How to Modify Props of Non-immediate Children - javascript

I am transferring my site from a LAMP stack to a MERN stack. On the old site, I had a dropdown where a button would toggle the display of a div of one of its parents siblings. The structure looked like this:
<div class="header">
<div class="header-option">Option 1</div>
<div class="header-option" id="toggle-dropdown">Option 2</div>
<div class="header-option">Option 3</div>
</div>
<div id="dropdown-content">
Lorem ipsum
</div>
I would use JQuery to detect a click on #toggle-dropdown and then toggle the display of #dropdown-content. I turned this into a reusable plugin which could be used throughout the site. I would now like to do something like this in React with a reusable component. But I cannot seem to find the best practice for accessing and modifying the props of non-immediate children. I would of course wrap all of this in a <Dropdown> component to handle the state and to be able to abstract the process.
What I have thought of and found so far:
Recursing through the children, and their children, and so on, looking for a displayName and then cloning the child; but I don't believe this works in production.
Taking JSX as a Header and Footer prop to Dropdown, and then attempting to generate the DropdownButton and DropdownContent within components with the appropriate props; I feel like this would be a very inefficient, undesirable solution to something that I feel should be relatively easy.

ok, so you have:
<Header>
<Option />
<Option onClick={this.handleDropdownclick} props={props}>
<Dropdown>
</Option>
<Option />
</Header>
right?
just pass the onClick handler to option you want, no?
Or didn't I understand what are you asking?
If your tree is very deep and you don't want to pass manually each prop, may be use Context? https://reactjs.org/docs/context.html#contextconsumer

Related

Is it possible to make a Web Component List with undetermined number of slot?

I know it can be achieved using Javascript by manually separate the slot elements and put them into the DOM tree but I wonder if it's supported within the box. Something like this:
<my-element>
<div slot="items">Item 1</div>
<div slot="items">Item 2</div>
<div slot="items">...</div>
</my-element>
And the template should be like this:
<div class="items">
<div class="item"> <!-- Should be 1 item per slot -->
<p>Something else</p>
<slot name="items"></slot>
</div>
</div>
Is this only possible using slotchange and populate the items by Javascript? Is there any better solution, without Javascript or with less Javascript? Maybe there is an element similar to slot that I am not aware of?
since all slot="items" will be slotted into <slot name="items"> only with the slotchange Event can the Component Author determine what happened.
Note: You do not populate the items, the default slotting mechanism does; you can only remove items after they are slotted; but then your HTML above needs more info on which Item needs to be slotted.
Then the question remains, Why use multiple slot="items" at all then?? If a slot can take 1 item, then only assign 1 item
Imperative Slots might help out: https://github.com/WICG/webcomponents/blob/gh-pages/proposals/Imperative-Shadow-DOM-Distribution-API.md
Update, I misunderdstood OPs question
All he needs to do is:
Create another Web Component: <slotted-item slot="items"></slotted-item>

Is it necessary to use Vuex for a Vue-based shopping cart?

I want to let two separate Vue components communicate with each other (not siblings, so not child or parent).
Let's assume I have a Laravel blade template file like that:
<div id="app">
<div class="header">
<shopping-cart></shopping-cart>
</div>
<div class="content">
<products-list></products-list>
</div>
</div>
How can I send a product from component to component (putting products to the cart) ?
If you want to get the right solution with the right structure, and it's simple, you have to use the State Manager(Vuex), because it's the best solution.
I wanted to write this in the comment, but I could not because I did not have enough reputation.

Setting raised = true to an ember button when on current page/template

<div class="flex">
<div class="layout-row layout-align-end-center">
{{#paper-button href="overview" raised=true primary=true}}Overview{{/paper-button}}
{{#paper-button href="incomes"}}Incomes{{/paper-button}}
{{#paper-button href="expenses"}}Expenses{{/paper-button}}
{{#paper-button href="settings"}}Settings{{/paper-button}}
</div>
</div>
So I am trying to set the raised=true whenever I am on certain page/template. The above code is from my application template. Is there any way of doing this using JS/Ember or should I just do it manually in each of my templates?
I think the best way to go is to write a custom component wrapping paper-button. ember-route-helpers gives you nice helpers to do that:
{{#paper-button
onclick={{transition-to #route)
href=(url-for #route)
raised=(is-active #route)
primary=(is-active #route)
}}
{{yield}}
{{/paper-button}}
Then you can use that component with {{#your-component route="settings"}}Settings{{/your-component}}.
It's important to understand that you should pass both the action and the href. Because then when people click on the button it will make a transition and dont reload the entire page, but rightlick->open and screenreaders are are not broken.

Why the scoped style in vue is useless? The parent element style still affect the child element

The Parent element style:
.container {
margin: 20px;
border:1px solid #f1f1f1;
font-size:14px;
font-weight:normal;
The child element style:
.container{}
But the child element style should be rendered like this:
why there are two data-v-*** in the child element and use the parent container style?
I know it's been ages, but I am going to add something here to help future people.
I encountered the same thing. Basically, I was nesting components within components, and being all fancy with scoped so that each component had a class called .container ... well to my surprise when rendering the styles started conflicting. I thought scoped was meant to fix this...
But apparently by design, that's not the case:
https://vue-loader.vuejs.org/guide/scoped-css.html#mixing-local-and-global-styles
With scoped, the parent component's styles will not leak into child components. However, a child component's root node will be affected by both the parent's scoped CSS and the child's scoped CSS. This is by design so that the parent can style the child root element for layout purposes.
So for instance, I have two components nested, I end up with this:
I have a view loading in two components:
<template>
<div>
<login-splash />
<login-form />
</div>
</template>
The two included are like this:
<template>
<div class="container">
<div>
<h1 class="big">Title</h1>
<h2 class="small">Subtitle</h2>
</div>
</div>
</template>
<template>
<div class="container">
<form class="form">
<label class="label">Username
<input class="input" type="input" name="username">
</label>
<label class="label">Password
<input class="input" type="password" name="password">
</label>
Forgot Password
</form>
<button-submit />
</div>
</template>
The issue is with button-submit which looks like this:
<template>
<div class="container">
<button class="button">Button</button>
</div>
</template>
Each of these files has scoped SCSS and it ends up producing the issue stated above.
This all ladders back to https://v2.vuejs.org/v2/style-guide/#Component-style-scoping-essential
Basically the solution is "use a class naming based solution like bem"... which isn't what anyone wants to hear when they see and use scoped and think it's a silver bullet... I know... but as with all web development, you gotta do what you gotta do.
If you are developing a large project, working with other developers, or sometimes include 3rd-party HTML/CSS (e.g. from Auth0), consistent scoping will ensure that your styles only apply to the components they are meant for.
Beyond the scoped attribute, using unique class names can help ensure that 3rd-party CSS does not apply to your own HTML. For example, many projects use the button, btn, or icon class names, so even if not using a strategy such as BEM, adding an app-specific and/or component-specific prefix (e.g. ButtonClose-icon) can provide some protection.
An alternative is to use CSS Modules, as stated in this answer:
https://stackoverflow.com/a/45900067/1034494
This ends up producing something like this:
There are two data-v attributes because you are specifying a CSS selector in the child component styles. The fact that it's empty does not change that. As long as you don't scope both components' styles, they will of course influence each other, especially if you choose identical class names.

How do I use a custom DOM node to render to from within a react component

I have the following problem:
I want to write jsx code like
<div className="my-section">
<Window>
<div>Window content</div>
</Window>
</div>
<div className="window-container">
</div>
somewhere in my react content, but I want the window to render in a special DOM element with other windows, something like
<div class="my-section"></div>
<div class="window-container">
<div class="window">
<div>Window Content</div>
</div>
</div>
And to do this transparently I need to tell the component to render to a special DOM node from within the component. Is there a way to do this? If not, how should I accomplish the functionality I am looking for from within React?
You're looking for the special this.props.children list.
When you create a React component instance, you can include additional React components or JavaScript expressions between the opening and closing tags like this:
<Parent><Child /></Parent>
Parent can read its children by accessing the special this.props.children prop.
This will allow you to get the children defined inside your element, then insert them at an arbitrary point for render.
render() {
return (
<div className="window container">
<div className="window">{this.props.children}</div>
<div className="window"></div>
...
</div>
);
}

Categories

Resources