Communication between two Angular 1 components - angularjs

I have a table component that displays at table, and a print component that displays the same table in a format ready for printing. Both reside in the same HTML page.
The print component needs some information from the table component. This information is useless to the outside controller, it just needs to get from one component to the other.
The obvious solution was to output-bind a printInfo object to the table component, and input-bind it to the print component, like so:
<table-component ... on-print-info-changed="vm.onPrintInfoChanged(info)"/>
<print-component print-info="vm.printInfo"/>
I set printInfo in onPrintInfoChanged.
while this works, it doesn't seem right. Since both components already rely on each other, I'd much rather do something like this:
<table-component .../>
<print-component table="<ref to table-component>"/>
That way the controllers doesn't need to know anything about the dependency between the two components, except that there is one.
The question is - how do I supply the reference to the table component? I can get the table controller's element on the page, but how do I get the component's controller from it?
I found some old (and sometimes contradicting) answers, but they were all relevant to old versions of Angular, before anybody used components or ES 6.

Related

Why is using React Context better than just passing around a props object?

I've been reading about the advantages of using Context in React and I am unconvinced. I'm wondering if there's something I've missed.
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
What's the hassle in creating a props object in the main component and just passing it around among the underlings? Something like:
// do this once at top level (I'm assuming [foo, foo_set] and [bar, bar_set] are state variables):
const props = {foo, foo_set, bar, bar_set, thisAndThat, theOther, whatever, etcAndEtc}
// including one component
<MyComponent1 {...props } />
// including another
<MyComponent2 {...props } />
(Maybe better to use another name than props for this object, as the components can have other properties. Anyway.)
Then in MyComponent1 you can access all the props you want, or not access them. Either:
...
const MyComponent1 = (props) => {
...
// here we can use any props we need, props.bar, props.bar_set, props.theOther for example
const localVar = props.bar * 2;
props.bar_set(localVar);
// this changes the value of bar throughout the app
...
}
the advantage of the above, as I see it, is that you can pass around the props object to other sub-sub-components and not worry about whether you have anything missing.
Or:
...
const MyComponent1 = ({bar, bar_set, theOther }) => {
...
// here we can use bar, bar_set, theOther in the same example
const localVar = bar * 2;
bar_set(localVar);
...
}
The advantage of this option being that the syntax is shorter.
So my point is why not just use the standard JavaScript syntax? Why introduce new concepts when there are plenty to assimilate to do all sorts of other things?
Consider a fairly common case for most applications: You have authentication information (eg, the current user), a routing library (eg, react-router), and a theme object (what colors to use). These are needed in components scattered throughout the app.
You want to render a button somewhere down at the tip of the component tree. It's going to show the user's avatar, so it needs the authentication data. It's going to navigate when clicked, so it needs the navigate function from the routing library. And it needs to style itself according to the theme.
This certainly can be done through props, but in order for the button to get the props, every component in the chain above it must get and forward those props too. This could be many components deep, like page component -> section component -> table -> row -> widget -> button, and most of them don't need that information for themselves, so they're just taking the props in order to forward it along.
And you can easily imagine cases where there are more than 3 pieces of data that are needed across the app.
What's the hassle
Most people find this "prop drilling" to be a hassle, but let's assume you don't. You still have the problem that it has bad performance. If every component must receive the full set of "global" values that the app might need, then any time anything changes, the entire app must rerender. Optimizations like react.memo become effectively useless. You will get much better performance if you only pass the props you need.
Easier to edit code (You don't have to delete for example unused variable)
Better redability (You dont see unnescesary variables, and You see which component is using variables)
Lesser performance waste (preventing from consuming unnescesarry variables)
Suppose You got 10 descendants in - You would have to pass one variable through 10 of components.
What if some could have the same variable name ? You would have to edit Your passed variable for a while, then edit back later.
To sum up:
Using Context more efficient than stuffing everything into a single object variable, because it avoids re-rendering the whole app when anything changes.
People think passing a single variable around is more hassle than introducing specific syntax.
Context also allows you to have different values for the same variable in different parts of the app. This is shown here (the best explanation IMHO) : https://beta.reactjs.org/learn/passing-data-deeply-with-context
The above article also specifies that sometimes passing props is the best solution. It gives a list of use cases for context, and the advantages provided in each case.

In React, is it possible to pass props & function calls between a parent component and its children when they're rendered between its component tags?

I've been using Stack Overflow forever, but I just made an account to ask my first question. Thanks in advance for all your help. Here goes:
I'm trying to work out the proper composition for these custom modular table filtering components I wrote and I could use a little guidance.
My table rows are stored in an array in the main page that these components will be displayed on. Each <TableFilter /> takes a specific column name of the table as a prop and renders UI to input and select filter options (e.g. for numeric columns there's a button that lets the user select <, >, =, etc.) and has a function to apply that filter and return only the selected rows from the table.
I've got these TableFilter components working great independently, but I'd like to be able to apply multiple filters at once. That's why I am working on a TableFilterGroup component that will contain the filters as children and handle passing data between them.
The plan is for easy use of the component, formatted like so:
<TableFilterGroup rows={this.state.tableRows} apply={this.applyFilters} >
<TableFilter column={'Name'} isNumeric={false} />
<TableFilter column={'ID'} isNumeric={true} />
<TableFilter column={'Color'} options={['Red', 'Blue', 'Green']} />
</TableFilterGroup>
I intend to have one "Apply Filters" button, rendered by the TableFilterGroup, that will iteratively call the filter functions of each of the TableFilter child components.
(^ Edit for clarity: this ApplyFilters() function of the TableFilterGroup will get the selected rows from filter 1, then pass them into filter 2 and so on, then finally call this.props.apply to set the fully-filtered rows to a state in the main page that holds these components as well as the actual table where the data is displayed.)
All of the TableFilter components need to work on the table data provided by the rows prop of their parent TableFilterGroup, and the TableFilterGroup needs to be able to iteratively call the filtering functions of each of its TableFilter children, letting their output (the filtered rows) waterfall to apply multiple filters simultaneously.
I've been reading about useRef and all the examples seem to be for the case of the child component being rendered in the return statement of the parent component, but I'm looking to add them in as children in between the two tags of the TableFilterGroup.
If anybody reading this has experience with this type of composition and is able to point me in the right direction, I would very much appreciate it! Or, if the consensus is that I'm just structuring this incorrectly overall, what would you suggest as a better way to format it? Thanks!

How to assign different values to 2 of the same child components in React

For example
I have a parent component named . This component contains 2 of the same components called . it looks like this so far
<Overview>
|<Stats>
|<Stats>
The Stats component contains html that looks like this.
Pic of Stats Component
Now the first time I insert <Stats> I want to assign values different from when I insert the second component. So in the screenshot there are numbers under each section. That is going to be the default numbers every time you insert the <Stats> component. How can I assign different numbers to every time I insert a <Stats> Component. I don't want the same numbers.
What I thought about doing was creating States in overview , for example Submitted, Redeemed...etc. Then in the component retrieve those states but assign itself new values. I have read setState needs to be used but for the life of me I cant figure it out.
Any Help would be greatly appreciated.
You can pass the numbers as props. Just give it a name, assign to that name in your opening JSX tag, and then reference it as this.props.yourPropName in the class. (If you are using classes) or props.yourPropName if the component is made with a function)
function Stats(props){
//your code
}
<Stats yourPropOne=5 yourPropTwo=3/>

Angular UI Router - any way of referencing the same url variable more than once?

I would like to implement finite netsing of ui router states (it is required by the client), the maximum depth of nesting can be a fixed value (for example 10) therefore i would like my states to look as such:
.state('page',{url:'page/{pageName}',templateUrl:...)
.state('page.page',{url:'/{pageName}',templateUrl:...)
.state('page.page.page',url:'/{pageName},templateUrl:...)
etc...
In the end i would like for user to be able to enter urls like:
'/page/page1/subpage1'
'/page/page2/subpage1/subsubpage2'
'/page/page3'
etc...
The obvious problem is that ui router will overwrite the 'pageName' variable for each (sub)state, therefore after navigating to /page/page1/subpage1 i will only have {pageName:'subppage1'} variable set in state 'page' and 'page.page'.
In the whole application the ui-sref would only use the RELATIVE states so when i am in the 'page' state i would go into 'page.page' state and so on. I would like to be able to move the html view of the page up or down the state hierarchy as needed, and i would like not to change every ui-sref call in such case (right now i would have to change the variable name because it has to have different name in every state)
Is there any possibility to achieve my desired scenario? i have tried defining 'pageName' as an array type, but it does not seem to work (gets overwriten for every substate). Using custom ui router type also seems to not work since it cannot modify stateParams objects, only returns the representation of single url value (therefore the 'pageName' is also overwritten).
Ui-router extras also seems not to help here, or maybe i am missing something.

Using itemId to fetch component Extjs

I had a problem with tab rendering. The contents of the tabs used to get mixed up as i used the same component on all the tabs and the component had sub-components with id. As the id would appear same on all panels, the components used to get mixed up. I am now using itemId instead of id and the tabs are getting rendered properly.
Now I am facing another problem. Initially I used Ext.getCmp(id) to fetch components in the controller. Now that ids are replaced by itemId, I am using the following:
Ext.getCmp(id).getComponent(itemId);
There is a deep nesting of components in the view and all the intermediate components have itemId. With the above statement, as I go on to fetch deeper components, the statements keeps extending like:
Ext.getCmp(id).getComponent(itemId1).getComponent(itemId2).getComponent(....;
Am I using the statement correctly? Is there a better shorthand method to achieve the purpose?
Please advice.
Basically you using it the right way because a itemId is only unique at component level (at least it has to). But as you might see this will get sort of ugly, therefore I strictly recommend you to use Ext.ComponentQuery or one of it's implementations up() and down() which are both available for most components. Where Ext.ComponentQuery will per default look through the all instantiated components up() and down() will start at the component from which they are executed, only walking through the existing component tree. Also up() and down() always returns the first match where Ext.ComponentQuery always present you a array.
Both accepting the same query string which can be written in various ways (here I recommend you to read the docs)
Here is a example for:
Ext.getCmp(íd).getComponent(itemId1).getComponent(itemId2)
expecting that you are using panels (it can be any component)
Ext.ComponentQuery.query('panel[id=yourId]>panel[itemId=yourId]>panel[itemId=yourId]');
lets say you are using MVC and therefore all your components are custom (have own xtypes). So if you know, that you have only one instance of 'yourcustompanel' with this itemId you may the simply call:
Ext.ComponentQuery.query('yourcustompanel[itemId=yourId]') // note you get always a array
You can use the Ext.ComponentQuery.query(..) or down() or up() to get the component you are referring to.
If you want to get a component(say a button) within a certain component(say within a container) ,you can use
var button = Ext.ComponentQuery.query('button[type=messageButton]', this);
In the above 'this' refers to the container scope.
Or you can use
var button = this.query('button[type=messageButton]');
In the above also 'this' refers to the container scope.
Hope this helps you ..

Resources