Aurelia How to get to function of composed child pages - aurelia

I have a parent form that loads child forms into tabs.
The parent looks like this:
<div repeat.for="app of Apps">
<compose if.bind='app.Url.startsWith("modules/")' view-model="${app.Url}"></compose>
</div>
So each of the "compose" tags loads a different page based on URL.
How can I find the specific page and call a function from that page's ts file?
I have a temporary solution in place by, on the parent, declaring a variable with:
childPage: any;
and then on the activate event of the child, I do:
parent.childPage = this;
Then, on the parent page, I have can do:childPage.childFunction();
This of course doesn't give me intellisense and won't work with multiple children, but for now, it meets my needs.

Related

Using inner component in a loop in Shopware 6 does not persist the values uniquely for each looped component

I am using a v-for over a custom component and passing the item as a prop. But the issue is that each component instance in the loop takes the same item prop. For e.g in the 1st loop a component field has text "abc", then the second looped component also will have the same "abc" text. If I change the text in the 2nd one, it changes in the 1st component too. Is there a way to make the prop unique for each loop ?
For e.g this is the code which calls the inner component:
<template v-for="(businesscase, index) in businessCase.fields">
<custom-case-freetext-field #field-changed="updateFields"
:key="index"
#field-removed="removeFields"
:fields="businessCase.fields"
:index="index">
</custom-case-freetext-field>
</template>
and inside this component I have a basic form
<sw-field :label="$tc('rma.modules.case.freetext.nameLabel')"
:placeholder="$tc('rma.modules.case.freetext.nameLabel')"
required
v-model="fields[index].name">
</sw-field>
<sw-single-select
labelValue="label"
valueProperty="label"
:options="fieldTypes"
:label="$tc('rma.modules.case.freetext.fieldType')"
:placeholder="$tc('rma.modules.case.freetext.fieldType')"
v-model="fields[index].type"
#input="changeType"
required>
</sw-single-select>
If I do :value instead of v-model, the entered value disappears as soon as the element loses focus.
If I use v-model, the data stays there, but then both (or as many are there in the loop) component instances, have data binding between them, so it defeats the purpose of having a loop for multiple components. As seen in the screenshot, I am typing in the 2nd component, but it changes the text for the first one too.
In the above example I am sending the whole array as prop, but I have also tried with individual field element instead of fields
Your are not using the businesscase variable inside your components. And since every component always works on the upper scope property, they will all change the same. Use the innerscope property. If you have problems with reactivity, because you try to mutate props directly work with events emitting the key and the changed value to the upperscope component.

asp-route-* not rendering query string inside view of view component

I have this anchor tag helper inside a view component:
<a asp-controller="Account" asp-action="Signup" asp-route-xxx="xxx" asp-route-returnUrl="/">Sign Up</a>
When it gets rendered in the browser, it looks like this:
It doesn't pass in the asp-route-* that I added. But the exact same tag helper I copy and pasted on a controller view, it gets rendered like this:
It contains the asp-route-* values in the query string. Do I need to do something to make it work for ViewComponents?

How to access composed children?

I have a list of composed elements:
<compose repeat.for="foo of someList" view-model="./bar" model.bind="foo">
Now, from the parent, I would like to call a function on a specific bar view model. How do I do that?
You can add view-model.ref in your compose tag:
<compose repeat.for="foo of someList" view-model="./bar" model.bind="foo" view-model.ref="foo.barviewmodel">
You can replace view-model.ref by compose.ref. The both give the same result.
And in the parent you can call a function on a bar view model like this:
this.someList[2].barviewmodel.currentViewModel.action();
It works, but I don't know if it's a public api. See this issue for more details

Accessing nested child components in VueJS

Using v2.2.2. I have the following structure in my VueJS app. How can I access all of the Account components from a method on my Post component? The number of Accounts is dynamic - I want to grab all of the loaded Account components and iterate over them.
I know it's got something to do with $refs and $children, I just can't seem to figure out the right path.
<Root>
<Post>
<AccountSelector>
<Account ref="anAccount"></Account>
<Account ref="anAccount"></Account>
<Account ref="anAccount"></Account>
</AccountSelector>
</Post>
</Root>
https://v2.vuejs.org/v2/guide/components.html#Child-Component-Refs
Despite the existence of props and events, sometimes you might still need to directly access a child component in JavaScript. To achieve this you have to assign a reference ID to the child component using ref. For example:
<div id="parent">
<user-profile ref="profile"></user-profile>
</div>
var parent = new Vue({ el: '#parent' })
// access child component instance
var child = parent.$refs.profile
When ref is used together with v-for, the ref you get will be an array
or an object containing the child components mirroring the data
source.
Basically inside AccountSelector.vue you can do this.$refs.anAccount.map(account => doThingToAccount(account))
Edit
The above answer is for accessing a direct child.
Currently there is no way to access a non direct parent / child component with $refs. The best way to get access to their data would be through events https://v2.vuejs.org/v2/guide/components.html#Non-Parent-Child-Communication or by using Vuex (Which i would recommend).
Non direct parent - child communication is very tricky without 1 of these 2 methods.
You can access nested components data using $refs and if you want to access the refs inside of it you first have to target the first element of the first refs ([0])
example: parent.$refs[0].$refs.anAccount

Overwrite data-dojo-props for title attribute in dijit/TitlePane

I have created a TitlePane and wish to load data dynamically from a get method into the Title property. As of the current this all works. However, now when the data is loaded (4 separate types), its all getting mushed together. I wish to divide this received data evenly (25%) across the title.
For example:
<div id="tp2" data-dojo-type="dijit/TitlePane" data-dojo-props="title: 'I'm a TitlePane
Too'">
Click arrow to close me.
</div>
In this example the title is set to "I'm a TitlePane Too".
I wish to change the title so that each of the four words is evenly distributed across the title section of the pane. However there are no extra properties for doing this sort of thing.
Use the "set" method to set the new title.
E.g:-
<div id="tp2" data-dojo-type="dijit/TitlePane" data-dojo-props="title: 'I'm a TitlePane
Too'">
Click arrow to close me.
</div>
//For this above example, title is replaced as follows in JS
dijit.byId('tp2').set('title','New title');
Update: If this title pane is created dynamically without an ID, then get the widget object using the css query.
dijit.getEnclosingWidget(dojo.query(".dijitTitlePane")[0]).set('title','New title');
dojo.query(".dijitTitlePane") => will give array of all titlepane domNodes. From this chose the one you need. I chose at "0"th index i.e. 1st title pane node in the page.
Then I get the widget object of that domNode and then set the title.