Reload angular component with button click - javascript

I working on a angular 8 application. In that application I want to reload a component, when a button clicked which is inside of another component. I found a way to do that with router, first navigate to sample component and then navigate to actual component as shown in below code.
this.router.navigateByUrl('/SampleComponent', { skipLocationChange: true });
this.router.navigate(["yourLandingComponent"]);
But in this application I don't have used router. This is simple, single page application. I have used ngIf to render components as shown in below.
<div class="row main-wrapper">
<app-section-rental class="container-fluid p-0" *ngIf="tabset.tab0"></app-section-rental>
<app-section-insuarance class="container-fluid p-0" *ngIf="tabset.tab1"></app-section-insuarance>
<app-section-additionals class="container-fluid p-0" *ngIf="tabset.tab2"></app-section-additionals>
<app-section-optionals class="container-fluid p-0" *ngIf="tabset.tab3"></app-section-optionals>
<app-price-breakdown class="container-fluid p-0" *ngIf="tabset.tab4"></app-price-breakdown>
</div>
So I want to know how to reload my component with a button click, which is inside of another component.
I also found another way to do this with angular subscription. But the problem is I that subscription get an element, I don't have to change any state which make any change in HTML. So I don't know whether my component get reloaded or not. Is it compulsory to do any change in DOM element, in order to reload a component ?

You could use Obersavables from rxjs.
This Observable contains the data displayed/updated in you component.
private _testSubject = new BehaviorSubject<string>('old data');
testObservable$: Observable<string> = this._testSubject.asObservable();
The following function will update your data:
public refresh(){
this._testSubject.next('new Data');
}
Call this function on you refresh-button's onClick.
And finally you can use your Observable in your components html like that:
<div>
{{(testObservable$|async)}}
</div>
Hope that helps!
EDIT:
As I noticed in your comments, your refresh button is in an parent component. In this case you could implement your observable in your parent component and work with an input in your comopnent:
#Input()
yourObservable: Observable<string>;
and in your parent component:
<app-your-compomemt [yourObservable]="testObservable$"></app-your-compomemt>

Related

How to send data from v-for to event handler in Vue?

I am having problems with sending the right data to the event handler of a subcomponent in my Vue component.
Here is my code:
<template>
<div>
<div v-for="item in [1, 2, 3]">
<div #click=test(item)>test</div>
<ConfirmModal v-if="showModal" #confirmed=test(item) />
<button v-on:click="showModal = true" ></button>
</div>
</div>
</template>
<script>
import ConfirmModal from 'ConfirmModal'
export default
{
components: {ConfirmModal},
data()
{
return {showModal: false}
},
methods:
{
test(item)
{
console.log(item);
this.showModal = false;
},
},
}
</script>
And here is the code for a subcomponent:
<template><div class="modal" #click.self="$emit('confirmed')">subtest</div></template>
So, basically, I here have an array of numbers and am using the v-for to iterate over an array.
For each item one test label, one subcomponent (containing a subtest label) and one button is created. When button is clicked, subcomponent is shown. When I click on the subcomponent (subtest label) it disappears.
div is a standard component which emmits #click events when it is clicked upon.
confirmModal is a very simple component which listens for #click events and redirects them into #confirmed events.
So, this code generates 3 times 3 items. When I click on any of the labels, test method is called which logs the value of the item.
When I click on any of the test labels, I get the correct value in the console, that is, 1 for the first item, 2 for the second item and so on.
But, when I click on any of the subtest labels, I allways get the 3, whichever link I clicked. (If I change the order of items in the array, then I allways get whichever item I put on the last place in the array).
I do not understand what is going on here, it is the same method called on the same way. Why is 3 allways logged in console when I click on the subtest label?
If you wonder what is class=modal in my subcomponent used for, I have no idea. This is a skeleton of two components in a very complex project consisting of thousands of files built on top of the Liferay, and there are more then ten files where is .modal defined in many directories. So I am not sure from which file does this particular component load this class. I did not throw it out of this skeleton code just because when I remove this class from the div in the subcomponent, everything works fine. I have no idea why. How can a class stop the correct data from being received? I do not get this.
I know that this bug may not be reproducable, because I did not provide the definition of the .modal style, but I posted it anyway, because I hope that you can see something else in the code what is wrong or propose another way how to execute the test method on #confirmed event.
I am using Vue 2.

conditional rendering in react using "if" how does the code reevaluate itself?

I'm grabbing some data from a redux action to pull into my React component. In the render() method, I am using an if/else check to see if that data was pulled in. IF the data is null and the "loading" boolean is still true, I want to display a spinner. ELSE - show the data.
When I hit the webpage, the component will show the spinner for half a second, as it's still null, then once the data is pulled in, it will show that.
my question is, in traditional JS, if the "if" statement is reached and the profile is still null will it not just stay on the spinner? Since that if/else expression on page load showed null should it not just stay on my spinner if that was the condition that was met on page load? How does it go back to that statement after the first run and hit the else block afterwards?
render() {
const {profile, loading} = this.props.profile;
let profileContent;
if(profile === null || loading){
profileContent = <Spinner/>;
} else {
profileContent = (
<div>
<div className="row">
<div className="col-md-6">
<Link to="/profiles">Back To Profiles</Link>
</div>
<div className="col-md-6"></div>
</div>
<ProfileHeader/>
<ProfileAbout/>
<ProfileCreds/>
<ProfileGithub/>
</div>
);
}
A React Component works by calling the render() function whenever the component state changes by default.
There are ways to modify this behavior by adding component lifecycle methods to your component.
Here is the official React documentation:
https://reactjs.org/docs/react-component.html

how to access value of state of Root Component in the child component

I have created a React application. In this application, I've created following components:
App Component (root) : where data is loaded into state
CardList Component: List of Cards, data is passed to it using props
Card Component: use forEach to pass data to Card and it has button
CustomButton Component: acts like a button with style
What I want is when the user clicks button on any of the Card, a number should get increased everytime. But I am not able to access Data here.
Can anyone help?
Here is the Card Component for your reference:
class Card extends Component {
render() {
return (
<div className="tc bg-light-green dib br3 pa3 ma2 grow bw2 shadow-5">
<h2>Votes: {this.props.votes}</h2>
<div>
<img src={this.props.pic} alt='Superstar'/>
<div>
<h2>{this.props.name}</h2>
<p>{this.props.email}</p>
</div>
</div>
<ActionButton btnText="Vote Now!" clickhandler={this.onVoteButtonClick}/>
</div>
);
}
onVoteButtonClick = (event) => {
console.log('It was clicked : '+this.props.id);
}
}
Two options which you should research more to see what suits your need best:
Redux (or something similar)
The new Context API available in React 16.
The gist of either solution is that you're managing application state independently of the dependent component tree(s). The Context API is arguably easier to implement whereas you'll currently find many more examples explaining the Redux approach as it's still the most common solution right now.

Vue.js v-for generated html block capturing collapse state with two way data binding

I'm trying to capture click action state (for collaps function) within html v-for generated block. To achieve this, I'm using declared data table, and it looks like state is being captured correctly. Below I'm ataching simplified v-for section, where I display state after click action. Displayed state is always false, even though after click, console.log shows table fields changes. Can someone please try to explain me why is that, and how to achieve what is expected here? I'm pretty new to vue, and must be doing something wrong...
<div v-for="address in userAddressData">
<a #click="expandControl(address.id)">
Address {{expandArea[address.id]}}
</a>
</div>
...
export default {
data () {
return {
userAddressData: '',
expandArea: [false,false,false]
}
},
methods: {
expandControl (id) {
this.expandArea[id] = !this.expandArea[id]
console.log(this.expandArea)
}
},
...
If I understood right, the problem you are having is that the template is not being updated according to the data, as we can see on this fiddle: https://jsfiddle.net/gen1kL3y/
This is issue is related to how Vue Reactivity works.
You can find another similar question here and I made a working JS fiddle for you here: https://jsfiddle.net/vz11zdjc/
Basically, instead of setting the value as this.expandArea[id] = !this.expandArea[id], you should (among other options) use Vue.set(this.expandArea, id, !this.expandArea[id])

React.js onShow event handler

I have a tabbed menu on my page, which is basically a bunch of divs that get shown/hidden depending on the tab that's clicked. I want to be able to refetch the data in a React Component in one of the divs once it appears.
componentDidMount fires at the very beginning, so it's not an option. It would be nice to just have an HTML event onShow similar to onClick but nothing like that seems to exist.
Any suggestions?
I have a Tabs component but in my case, all tabs content are mounted but not displayed. When I click on a tab, I just change the visibility with css
But to refetch data, you should make a component for the containers that fetch the data in his componentDidMount so, in the top level if you switch which one renders, the componentDidMount will trigger.
Put some code if you want some help with your case
Per the docs, componentDidUpdate is probably what you're looking for. It's called after props and/or state has changed and the component has re-rendered (not called for the initial render).
That said, it's probably simpler to just handle the data fetching in the onClick handler itself or better yet, fetch the data once in the parent component and pass down the relevant slice of data to the tabs and then show / hide as appropriate.
Hey You have to separate out the tab as component and render those component based on tab changed let me give one example over here.
Suppose I have one Page called MainPage in that Page I have Tab Control which Contain the Three tab First,Second and Third.
first you have to create a three Component like
var First=React.createClass({ // First Tab Content goes here });
var Second=React.createClass({// Second Tab Content goes here});
var Second=React.createClass({// Third Tab Content goes here});
Now your MainPage Should look like
var MainPage=React.createClass({
onClick:function(e)
{
if($(e.target).attr('id')=="1")
{
React.render(<First />,document.getElementById('tab-content'));
}
else if($(e.target).attr('id')=="2")
{
React.render(<Second />,document.getElementById('tab-content'));
}
if($(e.target).attr('id')=="3")
{
React.render(<Third />,document.getElementById('tab-content'));
}
},
render:function()
{
return(
<div>
<div>
//Three Tabl goes here
<div id="1" onClick={this.HandleTab}>Tab 1</div>
<div id="2" onClick={this.HandleTab}> Tab 2</div>
<div id="3" onClick={this.HandleTab}>Tab 3</div>
</div>
//your Container Div
<div id="tab-content">
</div>
</div>
)
}
})

Categories

Resources