# Custom element bind() lifecycle\`

**URL:** <https://discourse.aurelia.io/t/custom-element-bind-lifecycle/2185>\
**Category:** Help Requests\
**Created:** [January 28, 2019, 9:52pm UTC](https://discourse.aurelia.io/t/custom-element-bind-lifecycle/2185 "2019-01-28T21:52:10Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![jeremyholt](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/jeremyholt/32/1098_2.png) [@jeremyholt](https://discourse.aurelia.io/u/jeremyholt)\
**Post date:** [January 28, 2019, 9:52pm UTC](https://discourse.aurelia.io/t/custom-element-bind-lifecycle/2185/1 "2019-01-28T21:52:11Z")

</div>

A have a complex form with many custom elements. When the main form is loaded it queries the database and when the data is returned sets the property `public data: IDataClass = data-from-db`.

The main form then binds `data` to the various custom elements via  
`my-custom-element-data.bind='data'`

where each custom element has a @bindable public property called `my-custom-element-data`

So far so good.

The main form is bound to the data, as are all of the custom elements.

However, the problem is that I need to access the data in the custom elements as soon as the binding has occurred.

The logical place to do this in the custom element’s `bind()` method. However, it seems that the custom elements `bind()` method is called before the main form’s `bind()` method, so the data in the custom element is always `undefined`. I’ve also tried `attached()`.

The life-cycle seems to be something like:

1. customElement.bind() - the bindings for `data` are `undefined`
2. main form.bind() - the bindings for `data` are set correctly
3. custom element objects are now bound to `data`.

I would have thought it more logical that the bindings in the custom element would occur **after** the binding in their container.

How do I get at `data` in step 2) from the custom element?

I would like to avoid `EventAggregator` if that’s possible.

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [January 28, 2019, 10:55pm UTC](https://discourse.aurelia.io/t/custom-element-bind-lifecycle/2185/2 "2019-01-28T22:55:33Z")

</div>

From what you described, it seems you want to delay bind() of form elements to a point where data has been fetched.

There are few ways to resolve this

- you can either put the form in an if, only show when the form model value has returned from database query, this probably requires moving form model out of the form
- you can put an if on form elements, only show when the form model value has returned from database query. This similar yo the above but requires an if for every field
- you can change form element into more reactive/resilient to undefined value, so the initial bind wont affect it, and move the main logic into change hanfler of those form elements
- if the form is a component used by `<router-view/>`, then you can return a promise in activate lifecycle, where you delay the rendering by a call to database to query necessary data

---

<div class="post-metadata">

**Author:** ![jeremyholt](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/jeremyholt/32/1098_2.png) [@jeremyholt](https://discourse.aurelia.io/u/jeremyholt)\
**Post date:** [January 29, 2019, 9:26am UTC](https://discourse.aurelia.io/t/custom-element-bind-lifecycle/2185/3 "2019-01-29T09:26:28Z")

</div>

Oh man - you have no idea how your comments have helped!

If you’re interested please take a look at the original answer I wrote to your suggestions. As soon as I had finished writing it I realized that the easiest thing to do was to create a property (`uiInput`) on the data, and that simplified the code a million-fold.

So the html I ended up with in the custom element went from

```auto
 <span if.bind="(row.sector == 'Borrowings (+)' || row.sector == 'Repayments (-)') && selectedPeriod.period == 'Months'">
<span class="border p-1" contenteditable textcontent.bind="row.months[(selectedYear-1)*12+$index] | number" input.delegate="callback()"></span>
            </span>

<span if.bind="bindingNames().indexOf(row.sector) > -1">
              ${item | numberFormat: "0,0 | null" }
            </span>

```

to

```auto
<span if.bind="row.uiInput && selectedPeriod.period == 'Months'">
    <span class="border p-1" contenteditable textcontent.bind="row.months[(selectedYear-1)*12+$index] | number" input.delegate="callback()"></span>
</span>

<span else>
   ${item | numberFormat: "0,0 | null" }
 </span>

```

Again a million thanks for your help.  
All the best  
Jeremy

# Original answer to your comments

Your comments made me look at the code again.

In the main form where `costingService.calculateAllValus()` can take a long time

```auto
  protected calculateValues() {
    if (this.costing) {
      const { productionList, shellingCapacityMt, productionCosts } = this.costingsService.calculateAllValues(this.costing, this.selectedYear);

      this.productionList = productionList;
      this.shellingCapacityMt = shellingCapacityMt;
      this.productionCostsList = productionCosts;
    }
  }

  protected selectedYearChanged(year: number) {
    this.calculateValues();
  }

  protected selectedPeriodChanged() {
    this.calculateValues();
  }

  private async loadCostingByCompanyId(companyId: string) {
    this.costing = await this.costingsService.loadByCompanyId(companyId);

    this.costingsService.fillDefaultCosts(this.costing, this.dictionary);
    this.calculateValues();
  }

```

Main form html where the custom elements are all bound to `this.costing` and each utilize the bound values of `selectedYear` and `selectedPeriod`.

```auto
<div class="card-body">
      <fieldset>
        <legend>Select production year</legend>
        <select-production-year title="Purchases and Production" selected-year.two-way="selectedYear"
                                selected-period.two-way="selectedPeriod" periods-id="sp1" periods.bind="periods"
                                callback.call="calculateValues()"></select-production-year>
      </fieldset>

      <purchases id="purchases" costing.bind="costing" selected-year.bind="selectedYear" callback.call="calculateValues()">
      </purchases>

      <production id="production" production-list.bind="productionList" costing.bind="costing" selected-year.bind="selectedYear"
                  selected-period.bind="selectedPeriod" callback.call="calculateValues()"></production>

      <production-costs id="profit-and-loss" root.bind="productionCostsList" , selected-year.two-way="selectedYear"
                        selected-period.two-way="selectedPeriod" periods.bind="periods" costing.bind="costing"
                        callback.call="calculateValues()"></production-costs>

      <cashflow id="cashflow" root.bind="productionCostsList" , selected-year.two-way="selectedYear" 
                selected-period.two-way="selectedPeriod" periods.bind="periods" costing.bind="costing" callback.call="calculateValues()"></cashflow>

      <kpis id="kpis" root.bind="productionCostsList" , selected-year.two-way="selectedYear" selected-period.two-way="selectedPeriod" 
            periods.bind="periods" costing.bind="costing" callback.call="calculateValues()"></kpis>
...

```

and finally one of the custom elements `cashflow-custom-element.ts`

```auto
@autoinject
export class CashflowCustomElement {
  @bindable public selectedYear: number;
  @bindable public selectedPeriod: IPeriod;
  @bindable public root: IProductionCostsResults;
  @bindable public costing: ICosting;
  @bindable public callback: () => void;
  @bindable public periods: IPeriod[];

  constructor(private readonly productionCostsService: ProductionCostsService) { }

  public bindingNames() {
    return [
      "B/F",
      "Interest (-)",
      "Capital purchases machines (-)",
      "Civil engineering (-)",
      "P&L (+)",
      "Balance"
    ];
  }

  public bindingNamesFromCosting = () => this.costing.variables.productionCostsResults.cashflow.map(cf => cf.sector);

  public getValues(row: IExpenseItem) {
    if (row && this.selectedPeriod) {
      const startDate = this.costing ? this.costing.variables.dates.civilEngineeringEndDate : moment().format("YYYY-MM-DD");

      const values = this.productionCostsService.getRowValues(row, this.selectedYear, { period: this.selectedPeriod.period }, startDate);

      return values;
    }
  }
}

```

`cashflow-custom-element`

```auto
<template>

  <require from="./filter-value-converter"></require>
  <require from="./select-production-year-element"></require>
  <require from="./quick-links-element"></require>

  <fieldset>
    <quick-links legend="Cashflow"></quick-links>

    <select-production-year selected-year.two-way="selectedYear" selected-period.two-way="selectedPeriod" periods-id="spCashflow"
                            periods.bind="periods" show-periods="true" callback.call="callback()"></select-production-year>

    <table class="table table-sm table-borderless ${selectedPeriod.period == 'Quarters' ? 'quarter-highlight last-col-bold' : ''}">
      <thead>
        <tr class="small">
          <th style="width:20%"> </th>
          <th repeat.for="date of getValues(root.quantities[0]).dates" class="text-right">
            ${date | dateFormat: "MMM YY"}
          </th>
        </tr>
      </thead>

      <tbody>
        <tr repeat.for="row of root.cashflow" class="small ${row.name=='Header' ? 'font-weight-bold text-primary' : ''} ${row.sector=='Balance' ? 'font-weight-bold' : ''}">
          <td>${row.sector}</td>

          <td repeat.for="item of getValues(row).values" class="text-right" class.bind="item | 'posNegColor'">

            <span if.bind="(row.sector == 'Borrowings (+)' || row.sector == 'Repayments (-)') && selectedPeriod.period == 'Months'">
              <span class="border p-1" contenteditable textcontent.bind="row.months[(selectedYear-1)*12+$index] | number" input.delegate="callback()"></span>
            </span>

            <span if.bind="bindingNames().indexOf(row.sector) > -1">
              ${item | numberFormat: "0,0 | null" }
            </span>
          </td>
        </tr>
      </tbody>
    </table>
</template>

```

+++++++++++++++++++++++++++++++++

So the problem I am trying to solve is that the `bindNames()` function returns hard wired names for the binding rules used in the table.

What it should be doing is using the `bindingNamesFromCosting ()` function, but this doesn’t work because `costing` is not yet bound to the custom element at the time that its called…

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [January 29, 2019, 10:38am UTC](https://discourse.aurelia.io/t/custom-element-bind-lifecycle/2185/4 "2019-01-29T10:38:00Z")

</div>

Glad to see that, I believe you will simplify everything even more, as you go along 😄

---

<div class="post-metadata">

**Author:** ![jeremyholt](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/jeremyholt/32/1098_2.png) [@jeremyholt](https://discourse.aurelia.io/u/jeremyholt)\
**Post date:** [February 9, 2019, 9:39am UTC](https://discourse.aurelia.io/t/custom-element-bind-lifecycle/2185/5 "2019-02-09T09:39:41Z")

</div>

I just wanted to report back on what in the end was a really obvious solution.

The original problem was that the property I needed to access in the custom element was being bound after the data in the main page.

`custom-element-ts`

```auto
{
  @bindable public costing: ICosting
  public myProp: string;

  public myMethod(){
    if(this.costing){
       this.myProp = this.costing.variables.importantData;
    }
  }
}

```

The solution was simply to watch for the change on `costing` and instead of trying to call `myMethod()` in `attached` or `bind`, binding directly to the `myProp` property.

```auto
public costingChanged(costing: ICosting){
     this.myProp = this.costing.variables.importantData;
}

```

You were 100% correct when you said that I would simplify things as I go along 😄

---

<div class="post-metadata">

**Author:** ![bigopon](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/bigopon/32/18_2.png) [@bigopon](https://discourse.aurelia.io/u/bigopon)\
**Post date:** [February 9, 2019, 10:15am UTC](https://discourse.aurelia.io/t/custom-element-bind-lifecycle/2185/6 "2019-02-09T10:15:52Z")

</div>

The more you explore Aurelia, the more code you delete 😄
