Recommended way of conditionally rendering custom Vue components - javascript

in my parent render function, I am rendering a list of form inputs. They can be number, slider, text, etc, and for each, I have a custom Vue component, i.e. FormInputSlider. I receive some data from an API, and then have an array of these different inputs to render. Doing a huge if/else block in my parent's render code seems unmaintainable, so what is the best/standard way of rendering a FormInputSlider component when I encounter a "form-input-slider" in the list iteration? I'm coming from a React understanding of the world for what it's worth.

If you've the component names, you could just use the built-in component tag to render the component dynamically :
<component :is="dynamicName" />
instead of :
<template v-if="dynamicName==='abc'">
<abc/>
</template>
<template v-elseif="dynamicName==='xyz'">
<xyz/>
</template>
....

Related

Removing components from the DOM in Vue.js

I am rendering some components using Vue.js (version 3.x)
<div v-for="(i, index) in fields" >
<my-component :id="index" ></my-component>
<span class="delete-icon" #click="removeField(index)" >×</span>
</div>
Where fields is simply an array like so: [0,1,2,3,4,...]
Vue renders as many components as there are elements in fields along with the spans having the delete-icon which have an event listener to fire the removeField() function, which takes the index of the rendered component and is meant to be used to remove the respective component from the DOM.
However, I am not sure how to indicate to Vue that a specific component needs to be removed - in other words, how do I tell Vue to remove the particular component who's delete icon I click, as opposed to just deleting an element from the fields array, which will re-render the set with one less component, always resulting in the last component being removed.
I am passing unique id's to the components as well, so I technically can remove the components using vanilla JS, but wondering whether Vue offers a more elegant solution.
You can create a method that will filter the fields
It is not recommended to use index as a unique key.
CODESANDBOX
removeField(index) {
this.fields = this.fields.filter((number, i) => {
return i !== index;
});
},

How to pass rendered Vue component as parameter?

I use Vue, vue-fontawesome and v-tooltip. What I simply try to do is this:
<button v-tooltip="<fa icon='sign-out-alt'/>">Upgrade</button>
But that doesn't work, component passed as strings are not rendered. How to get it done easy way?
In this specific use case, there's an example for that in v-tooltip readme
If you need to display components inside the tooltip (or
popover/dropdown, technically it's the same 😄), use the v-popover
component
Here's an example of using a child component as a popover. Instead of my child component, you would use your <fa icon='sign-out-alt'/> icon.

Should you hide modals or remove them from the DOM in React?

I'm writing a React application with a lot of modals (but only one ever active at a time with no nested modals), and I'm unsure of which of these two solutions is preferable when it comes to handling showing and hiding these modals:
Have a state boolean variable in the parent component that determines whether or not the modal should be shown. If this boolean variable is false, don't render the component. If it's true, render it. Allow the modal to influence this event via a passed in props callback it can leverage. Example snippets:
{ this.state.prompt === "makePW" ?
<MakePassword closeModal={this.closePWModal} /> :
null
}
Now, within the component, it is always visible and does not control its lifecycle. If it is being rendered then it is visible.
Just always show the component in the parent component, like so:
<MakePassword />
Then within the component itself handle its entire lifecycle. That is, the component will have a boolean state variable for its visibility. Some snippets for this approach:
<Modal open={this.state.open} onClose={this.closeModal}>
<Modal.Header>Header</Modal.Header>
<Modal.Content>Body</Modal.Content>
</Modal>
There are also hybrid approaches, and other solutions as well I'm sure.
Regardless, I suppose the essence of my question is wondering about the preferable solution for showing and hiding modals: is it to always render them and just toggle their visibility, or to actually toggle between adding and removing them from the DOM? And, should the modal itself generally control its lifecycle or should the parent?
i prefer 1st one but if you want to use the second , i would extend the makepassword component from PureComponent to optimize your component.
Instead of writing shouldComponentUpdate() by hand, you can inherit from React.PureComponent. It is equivalent to implementing shouldComponentUpdate() with a shallow comparison of current and previous props and state. - source react docs
class MakePassword extends React.PureComponent{
...
}
I think it depends on your application.
For example, React-Bootstrap modals stay in the DOM and that allows for nice in/out animations.

Where should I put data and methods within nested components?

I'm trying to understand how I can do the following flow in React
page load
ajaxA()
-return dataA
-render dropdown HTML
-ajaxB(dataA)
-return dataB
-render chart HTML
handleDropdownChange()
-ajaxB()
-return dataB
-render chart HTML
I have it split out into two components
a top section with controls (ajaxA returns data to build some dropdowns.
a couple of chart below. When one of the dropdowns in the top part changes, then the chart should update.
Should ParentApp contain all methods for updating the charts and data related to child components, passing both in as props, eg:
handleControlChange (event) {
this.setState(selectedOption: event.target.value)
},
render () {
return (
<ParentApp>
<Controls
handleControlChange={this.handleControlChange} />
<Chart />
</ParentApp>
)
}
or should that functionality live within the Controls component? The second way seems more reasonable to me but since Controls and Chart are siblings I'm not sure how I can pass data to Chart when there is a change within`Controls. As I understand it data only flows from parents to children in React. It seems like ParentApp would soon contain basically all the methods needed by its children components which kind of seems it goes against keeping components modular.
Where should I store my data and my methods to interact with it?
In principle React only lift the state up when this state must be shared between siblings and/or parent, when a child component doesn't need to send its state to parent or siblings it can have its own state and no lifting up is needed.
But practically speaking most apps will have state in central place at parent component, there are even libraries for central states like Redux , that being said we didn't lose modularity in any way because state is only part of the story, for example spliting the app into components will give you modularity in rendering, also because child components takes props you can reuse the same component in multiple places with different props to control its appearance almost the same way you change the appearance of an <a> link by just applying a class.

Nested components in Vue.js

I struggle in creating nested components where each layer includes templates:
<wizard>
<step name="first">Do this step first!</step>
<step name="second">This should follow</step>
</wizard>
(full example: http://jsfiddle.net/maxhq/9o4qxd7t/)
I only get templates to work either for parent or for child components, never for both.
if parent has no template and is used with <... inline-template>, child components (and their templates) are evaluated (like in http://jsfiddle.net/hajkrupo/3/)
if parent includes a template (even with special tag <content>), then the child components do not get inserted/evaluated
Can this be solved in vue.js?
If you're using the latest vue.js version (1.0.26 at the time of writing) your problem is using <content></content> as the syntax was changed to <slot></slot>
JSFiddle
No. inline-template means you define template inline there there:
When this param is present, the component will use its inner content as its template rather than transclusion content. This allows more flexible template-authoring.
You can do it this way: http://jsfiddle.net/8k335nrf/

Categories