I use Polymer, Html and Javascript.
I want to find any easy way to call a function from one polymer component to another.
Let me describe what I want to achieve.
I have polymer component myComponent. In this component container with button called start:
<button on-click="_start" id="start">XyZ</button>
and also second component (let's say it is child component, because it is in myComponent, where I have got function _addNew in <script> section.
Now I want to fire _addNew function by clicking button with #start id.
My question is how can I call a function from one polymer component when this function is placed in another?
I hope you understand me.
if I understood correctly, basically what you want to do is fire from one component and listen in the other one.
So you fire from myComponent, in the _start method like:
this.fire('add:new');
and then to listen to the add:new event in your other component by adding a listener, for this specific event name:
listeners: {
'add:new': '_addNew'
},
if it's not explicit enough, please do read the Polymer documentation it's a very nice and well explained documentation.
Hope it helps.
In my case this is not working, because this.fire is going "up", to the parent component, not to a child component.
In my case this one help:
this.$$('component-name').function-name();
Related
I want to get an event that is fired relatively on the top of the dom-hierarchy to a child component further down the hierarchy.The child is not a direct child of the parent
I understand that I do that with the input-decorator. Please note doing it the other way around like it should be is not possible.
The html of the parent looks like this
<element [data]="viewData" (anext)=OnNext($event)></element>
I need to get the $event available in the child. How do I achieve this?
You can create a service with an rxjs Subject, as shown in the psuedo code below.
//Evservice.ts
public subject = new Subject();
OnNext(event) {
subject.next(event)
}
//childComponent.ts
constructor(ser: Evservice)
ser.subject.subscribe((ev) => {//access your event here});
I'm using React Hooks.I am trying to trigger a onclick event using useRef.
const component1: React.FC<Props> = props {
const node =useRef<HTMLDivElement>(null);
const ClickListener = UseCallback((e:any)=>{
if(node.current.contains(e.target))
console.log("Event Contained");
else console.log("Event not Contained");
},[]);
return (
<div ref={node} onClick={ClickListener}>
<FormControl>
<InputLabel>{text}</InputLabel>
<Select> {contents} </Select>
</FormControl>
</div>
);
};
I have this Component1 called by componentX and componentY.
The above code is failing to recognise onclick event on a componentX's node when componentY's select menu is opened.
Only after closing ComponentY's select menu and clicking again on ComponentX currently recognises the event.
Any Suggestions on why itsn't recognized.I am using Material UI's select.
Use callback ref.
Quoting from API doc:
Keep in mind that useRef doesn’t notify you when its content changes.
Mutating the .current property doesn’t cause a re-render. If you want
to run some code when React attaches or detaches a ref to a DOM node,
you may want to use a callback ref instead.
Edit
Sorry to lead you in wrong direction. My suggestion to use callback ref is not correct for your code.
Your callbacks are working correctly and are able to use the div ref properly.
The reason you feel your callback is not working when Select in other component is opened is that Select uses mouse capture to detect click outside the pop-up.
So when your drop-down is open, click on other component div does not reach that div at all, it is consumed by Select. Subsequent click works well.
This is the case not only with your component but with any other element in the dom.
See: https://codesandbox.io/s/silly-star-k430x
You should pass node in the dependancy list to the useCallback method.
Otherwise, the node which refers to null while defining the ClickListener is not updated.
Go through the docs - useCallback. useCallback avoids redefining the function every time the component function is called. So any global variables inside the function definition has to be listed in dependancies array, so that react will redefine the function when ever the dependancies change.
const ClickListener =UseCallback((e:any)=>{
if(node.current.contains(e.target))
console.log("Event Contained");
else console.log("Event not Contained");
},[node]);
I am trying to trigger an onClick function call inside a sub-component by adding the onClick to the parent component. It does not work.
// parent component
class MainForm extends Component {
// code here
handleClick = () => {
console.log('clicked!');
}
render {
return (
<Linkbutton
text="Click Me!"
onClick={this.handleClick}>
/>
);
};
// sub component
export const LinkButton = (props) => {
return (
<button>{props.text}</button>
);
};
This did not work. The onClick function was not being called on click. I managed to fix it by adding the onClick call in the sub-component as well.
// sub component
export const LinkButton = (props) => {
return (
<button onClick={props.onClick}>{props.text}</button>
);
};
This worked. My question is why? Shouldn't the onClick be called on any element regardless of what is inside it? Why did I have to explicitly pass it down to the sub-component as well?
I would like to understand the reason for it being this way and why it wouldn't work the first way I tried. Thanks!
The reason is that the LinkButton component you created is just a javascript object, not a DOM node, so it does not have event handlers like onClick. The button element is transformed into the actual DOM element so it will have all the associated event handlers that the actual HTML element.
When you add an onClick prop to the LinkButton component, it is just a property of an object. By calling props.onClick from inside of that component you are just calling a function that is stored inside of a property, similar to this:
let props = {
onClick: function () { alert("Executed!"); }
};
props.onClick();
Hope this helps you!
In your first example, you are not actually adding the onClick event. Just passing the reference to the component doesn't mean it automatically know what to do with it.
The second example does actually add the onClick to the button, like it should, which is why it works.
In your first example, you are using "onClick" as a parameter, not as the actual event handler.
you are in little confusion. onClick props you have passed in Linkbutton component doesn't trigger your function call. in react we use props in order to communicate between components. onClick is an event in button element while onClick is props in Linkbutton component.
Unfortuantely, there is no way around that in pure React.js. If you want the parent element's function to handle click event performed on a child element, you have to explicitly pass that function as a prop to the child element.
I understand why it may seem frustrating at times, especially if you have got a tall component tree and numerous leafs of that tree that have to call a method of parent, parent of the parent, or even parent of the parent of the parent [ ... ] element.
One way to mitigate that problem (especially when your project grows big) would be to use a state store that implements the Flux pattern. Good example of that would be Redux. Instead of calling a method passed from the parent component as a prop (such method would in most cases alter the sate of the parent component), your button component would dispatch an action that would then be taken care of by a reducer function, consequently updating the global state of the application. All components of the app that rely on the part of the global state that got changed would then be updated accordingly. In this example, the button component would not communicate with the parent element directly. It would just dispatch an action.
Here is a great tutorial that you should read if you decide to learn Redux. Bare in mind that Redux is commonly considered to be somewhat difficult to start with, therefore it's best suited for big apps where initial increase in project complexity caused by the addition of Redux to the app is outweighed by added ability to avoid all the problems resulting from direct communication between components.
The following is my component tree.
DashboardComponent
TaskManagementView
TaskManagementForm
SubmitButtonComponent
I need to pass the button clicked event from SubmitButtonComponent to the DashboardComponent.
One way of doing this would be as follows
<DashboardComponenet AddTask={AddSomeTask}>
....
<TaskMangementView submitClicked={props.AddTask}>
....
<TaskManagementForm ButtonClick={props.submitClicked}/>
.....
<SubmitButtonComponent onclick={props.ButtonClick}/>
....
<TaskManagementForm />
....
</TaskManagementView >
....
</DashboardComponent>
Is there some good way of passing the onClick to the DashboardComponent ? This is hard to maintain.
As Gaurav said, you can either pass the function down through the components as props. But this can get messy when there are many components in the middle
OR
I would recommend using something like Context which will allow you to skip components in the middle and just access the function where needed.
Hi I am using an UI Library (forced to, company issue..) which provides an Angular component, which renders a form.
Now I want to disable all of the input fields an buttons inside this form. But the component of the library doesn't provide me the possibility to pass a parameter to change the status to read only.
Now I have no other option to do dirty DOM hacking. However it doesn't seem to work.
Here is my HTML of my own component, where I render the Library Component:
<component-of-the-library #formComponent></component-of-the-library>
Now inside my own components class I reference it:
#ViewChild('formComponent', {read: ElementRef}) formComponent: ElementRef;
However when I use the nativeElement feature and the querySelectorAll() function I don't see the button elements:
ngAfterViewInit() {
console.log(this.formComponent.nativeElement);
console.log(this.formComponent.nativeElement.querySelectorAll('button'))
}
The first line outputs the DOM of the library component. There I also see the buttons.
However the second line just returns an empty NodeList.
Am I missing something?
Instead of doing all these, come up with a div overlay and with the size of your form and make show or hide it based on your needs.
It will be easier than disabling each form inputs and buttons. Also the overlay is not the component but your div.
I able to read the DOM Nodes present in the child component from the parent Component using ViewChild() https://stackblitz.com/edit/angular-edmyur?file=src%2Fapp%2Fapp.component.ts
EDIT: I see another problem. AfterViewChecked gets called multiple times...
I found the answer myself. The problem is the LifeCycleHook. AfterViewInit works for your own component, but it doesn't wait for the child components to finish rendering.
When I use AfterViewChecked it works!
However I am still puzzled, that logging the nativeElement has always given me the correct DOM, even though it's still not rendered.