My Blazor web app is giving me this error when I try to view a page - error-handling

I do not know what the below error is trying to tell me...
Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Object reference not set to an instance of an object.
System.NullReferenceException: Object reference not set to an instance of an object.
at GSG.WebApp.Client.Pages.Index.BuildRenderTree(RenderTreeBuilder __builder) in C:\Users\ZachKoman\internalhrtool\GSG.WebApp\Client\Pages\Index.razor:line 0
at Microsoft.AspNetCore.Components.ComponentBase.<.ctor>b__6_0(RenderTreeBuilder builder)
at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException)
The error began when I tried testing these filter input boxes.
<!--Input fields for filtering-->
<div style="display:flex">
<div class="filter">
<BSLabel style="width=20%">Lastname: </BSLabel >
<BSInput InputType="InputType.Text" placeholder="name" #bind-Value="lastname" />
</div>
<div class="filter">
<BSLabel style="width=20%">Company: </BSLabel>
<BSInput InputType="InputType.Text" placeholder="Company" #bind-Value="company"/>
</div>
<div class="filter">
<BSLabel style="width=20%">Skill: </BSLabel>
<BSInput InputType="InputType.Text" placeholder="Skill" #bind-Value="skill[0]"/>
</div>
#for (int i = 1; i < skillFilterStatus; i++)
{
<div class="filter">
<BSLabel style="width=20%">Skill: </BSLabel>
<BSInput InputType="InputType.Text" placeholder="Skill" #bind-Value="skill[i]"/>
</div>
}
#if(skillFilterStatus != 0)
{
<div class="filterBttn">
<BSButton style="background-color: #ed1c24;" #onclick="FilterMinus"><i class="oi oi-minus" style="color: white" ></i></BSButton>
</div>
}
#if(skillFilterStatus < 2)
{
<div class="filterBttn">
<BSButton style="background-color: #8522e4;" #onclick="FilterClick"><i class="oi oi-plus" style="color: white" ></i></BSButton>
</div>
}
<div class="filterBttn">
<BSButton #onclick="ApplyFilter" style="background-color: #8522e4; color: white">Apply</BSButton>
</div>
</div>
#code
private int skillFilterStatus = 0;
private string lastname;
private string company;
private string[] skill;
private void ApplyFilter(){
Console.WriteLine(lastname+"-"+company+"-"+skill[0]+"-"+skill[1]+"-"+skill[2]);
}

Related

vue+bulma Tabs Error:'openTab' is defined but never used

I would like to create a tab using vue and bulma, but I'm getting the following error:
error: 'openTab' is defined but never used (no-unused-vars) at
code:
<template>
<div>
<div class="tabs is-centered">
<ul>
<li class="tab is-active" onclick="openTab(e,'adult')"><a>Adult</a></li>
<li class="tab" onclick="openTab(e,'card')"><a>Card</a></li>
<li class="tab" onclick="openTab(e,'food')"><a>Food</a></li>
</ul>
</div>
<div id="adult" class="content-tab">
<img :src="require(`../../static/dst/${parentData.file_name}`)">
<div v-bind:style="{ color: `${parentData.font_color}`}">
{{parentData.info_text}}<br>
{{parentData.rate_adult}}{{parentData.part_name}}<br>
{{parentData.rate_part}}
</div>
</div>
<div id="card" class="content-tab" style="display: none">
<div :style="{ color: `${parentData.card_color}`}">
{{parentData.card_text}}
</div>
</div>
<div id="food" class="content-tab" style="display: none">
{{parentData.class_name}}
</div>
</div>
</template>
<script>
export default {
name: 'Child',
props: ['parentData'],
openTab(e, tabName) {
var i, x, tablinks;
x = document.getElementsByClassName("content-tab");
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tab");
for (i = 0; i < x.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" is-active", "");
}
document.getElementById(tabName).style.display = "block";
e.currentTarget.className += " is-active";
}
}
</script>
                               
I want to find the answer to this problem.
Tap function does not apply.
Process:
Upload an image
Return json contents
Check by tap
Can you tell me what the error is?
Your openTabs function should be part of methods. So:
props: {},
methods: {
openTab()
}
More information here: https://v2.vuejs.org/v2/guide/events.html#Method-Event-Handlers

How to collapse/expand Razor components using Blazor syntax?

I'm currently implementing a form to create a new user along with their respective user rights. In this form, I have about 30 different IT systems and if the user account should have the access rights for that specific IT system, I want to provide a panel to the admin where some extra information must be entered regarding that specific IT system. I want to implement this using razor components. What I have so far is the core view for my "new user form" as well as a razor component for the additional information of a specific IT system. By clicking the + button, I want the component to be visible / expand right below the IT system. That's what It looks like so far:
The new user form:
<div class="row">
<div class="col-sm-2 font-weight-bold">GOODWILL PKW/Smart</div>
<div class="col-sm-2">
<label>Add</label>
<input type="checkbox" />
</div>
<div class="col-sm-2">
<label>Change</label>
<input type="checkbox" />
</div>
<div class="col-sm-2">
<label>Remove</label>
<input type="checkbox" />
</div>
<div class="col-sm-4">
<button #onclick="#collapseGoodwill">+</button>
</div>
</div>
<ModalGoodwillPKW ></ModalGoodwillPKW>
#code {
public void collapseGoodwill() {
}
}
The component:
<div class="panel panel-default border">
<div class="panel-heading alert-primary">
<h3 class="panel-title">Goodwill PKW/smart</h3>
</div>
<div class="panel-body">
<div class="container-fluid">
<div class="row">
<div class="col-sm-2 font-weight-bold">Profile</div>
<div class="col-sm-5">
<input type="checkbox" id="CB_c" />
<label>Salesman</label>
</div>
<div class="col-sm-5">
<input type="checkbox" id="CB_r" />
<label>Administrator</label>
</div>
</div>
</div>
</div>
</div>
Normally, I would use JQuery in the "collapseGoodwill" method to add a .collapse class to this element. But since I am experimenting with Blazor, I'd like to know if there is a 100% Javascript /JQuery free way of doing this.
Thanks!
Within Blazor, you always follow the pattern:
change data
--> new view rendered
Anytime you want to change the component's UI from outside, you should do it by changing the data (model/state/parameter/context/...).
As for this scenario, you can add a Collapsed field to indicate whether the panel itself is collapsed now:
<div class="panel panel-default border #Collapse">
<div class="panel-heading alert-primary">
<h3 class="panel-title">Goodwill PKW/smart</h3>
</div>
<div class="panel-body">
<div class="container-fluid">
<div class="row">
<div class="col-sm-2 font-weight-bold">Profile</div>
<div class="col-sm-5">
<input type="checkbox" id="CB_c" />
<label>Salesman</label>
</div>
<div class="col-sm-5">
<input type="checkbox" id="CB_r" />
<label>Administrator</label>
</div>
</div>
</div>
</div>
</div>
#code{
[Parameter]
public string Collapse{get;set;}="collapse"; // hide by default
}
And whenever you want to collapse it, just set this parameter to collapse:
<div class="row">
<div class="col-sm-2 font-weight-bold">GOODWILL PKW/Smart</div>
<div class="col-sm-2">
<label>Add</label>
<input type="checkbox" />
</div>
<div class="col-sm-2">
<label>Change</label>
<input type="checkbox" />
</div>
<div class="col-sm-2">
<label>Remove</label>
<input type="checkbox" />
</div>
<div class="col-sm-4">
<button #onclick="e => this.Collapsed = !this.Collapsed">
#( this.Collapsed ? "+" : "-")
</button>
</div>
</div>
<ModalGoodwillPKW Collapse="#( this.Collapsed ? "collapse": "")" ></ModalGoodwillPKW>
#code {
private bool Collapsed = true;
}
Demo:
[Edit] : we can even refactor the above code to expose less information by changing the field from string to boolean.
The ModalGoodwillPKW.razor:
<div class="panel panel-default border #(Collapsed? "collapse": "" ) ">
<div class="panel-heading alert-primary">
<h3 class="panel-title">Goodwill PKW/smart</h3>
</div>
...
#code{
[Parameter]
public bool Collapsed{get;set;}= true; // hide by default
}
The UserForm.razor:
<div class="row">
...
<div class="col-sm-4">
<button #onclick="e => this.Collapsed = !this.Collapsed">
#( this.Collapsed ? "+" : "-")
</button>
</div>
</div>
<ModalGoodwillPKW Collapsed="#Collapsed" ></ModalGoodwillPKW>
#code {
private bool Collapsed = true;
}
I had a similar issue, I had a dynamic list of sections that I wanted to collapse, and I couldn't get the bootstrap data-toggle approach to work due to Blazor mis-handling of # anchor tags.
I used the component idea:
<div class="row">
#if (Collapsed)
{
<span #onclick="#Toggle" class="oi oi-plus mr-1"/>
}
else
{
<span #onclick="#Toggle" class="oi oi-minus mr-1"/>
}
#Title
</div>
#if(!Collapsed)
{
#ChildContent
}
#code {
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public bool Collapsed { get; set; }
[Parameter]
public string Title { get; set; }
void Toggle()
{
Collapsed = !Collapsed;
}
}
Which I could then use like this:
#foreach (var i in c.Request)
{
<Collapsable Title="#i.SectionName" Collapsed="true">
<ChildContent>
#foreach (var kvp in i.Values)
{
<div class="row">
<div class="col-1"></div>
<div class="col-6 font-weight-bolder">#kvp.Key</div>
<div class="col-5">#kvp.Value</div>
</div>
}
</ChildContent>
</Collapsable>
}
This seems to work well, each section is independently collapsible.
I've not tried it nested though.
Blazor "#Collapse" div with Bootstrap Toggle Button
I took #cjb110 's excellent sample code above and changed it to use a bootstrap badge button as the toggle, which is how I often add more verbose help info to a form field group, by hiding it behind a toggle and using a bootstrap or material info button for if a user wants it.
Component Part
Here's the component part, which you'd probably add to your Blazor solution's Client project's Shared folder as file name Collapsible.razor (note: Blazor component file names are to be capitalized--I think)
<div class="my-1">
<h3>#Title</h3>
#if (Collapsed)
{
<button #onclick="#Toggle" class="badge badge-info mr-2" role="button" >
#ButtonText
</button>
}
else
{
<button #onclick="#Toggle" class="badge badge-info mr-2" role="button" >
#ButtonText
</button>
}
<label>
#LabelText
</label>
</div>
#if(!Collapsed)
{
<div class="card alert alert-info mb-3" role="alert">
#ChildContent
</div>
}
#code {
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public bool Collapsed { get; set; }
//input params coming from from page
[Parameter]
public string Title { get; set; }
[Parameter]
public string ButtonText { get; set; }
[Parameter]
public string LabelText { get; set; }
void Toggle()
{
Collapsed = !Collapsed;
}
}
Template Part
I call this the "template" part. You can change the
Title text,
ButtonText,
I use these info-btn toggles typically in forms, so I added a
<label/> tag with LabelText.
In the <ChildContent/> area, in the component file I set it up as a Bootstrap alert class div, so it doesn't require a <p> tag, but put anything in here you want to show up when the toggle is opened.
<Collapsible
Title=""
ButtonText="Info"
LabelText="Search People & Assign Roles: "
Collapsed="true">
<ChildContent>
Find a person, add their role to the product (i.e.: Estimator, Foreman, Customer)
</ChildContent>
</Collapsible>
I was facing issues with the accordion collapse in my project.
This is how I fixed the bootstrap collapse issue in my Blazor app.
I simply copied these dependencies in the index.html file in Blazor webapp and it worked fine.
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
Reference: https://www.w3schools.com/bootstrap4/tryit.asp?filename=trybs_collapsible&stacked=h
Let us know if this works for anyone else
There are some long and good answers. I thought I'd come in with the most important punchline, though.
You can hide whatever you want based on C# conditional logic. So you will VERY often use something like:
<div #onclick="()=>IsOpened = !IsOpened">Click on me to show the hidden control.</div>
#if (IsOpened){
<MyHiddenControl />
}
#code {
bool IsOpened;
}

Populate Knockout's observable array from Razor

I'm trying to implement error handling in ASP.NET so that if there is an error the user will get the error message, then be able to go back and have the previous state restored. I'm using ASP.NET Core and Knockout (not my implementation). I want to update "signerFields" with the model from the server (Model.SignersJson). How would I do this?
Signer.js
function SignerViewModel() {
var self = this;
self.signerFields = ko.observableArray([]);
self.guarantorFields = ko.observableArray([]);
self.companyGuarantorFields = ko.observableArray([]);
...
Signer.cshtml
<div data-bind="foreach: signerFields, visible: signerFields().length > 0">
<div class="row">
<div class="col-lg-10">
<div>
#*Header Company signers section*#
<div class="row" data-bind="visible: isCompany() && !anySigner() && !isInvitation()" style="display: none">
<div class="col-lg-4">
<b>FullName</b>
</div>
#*<div class="col-lg-3">
<b>LastName </b>
</div>*#
<div class="col-lg-4">
<b>Role </b>
</div>
<div class="col-lg-3">
<b>Contact_Information</b>
</div>
</div>
</div>
</div>
...
#section scripts
{
<script src="~/Scripts/Signer.js"></script>
var serverSigners = JSON.parse(#Html.Raw(Json.Encode(Model.SignersJson)));
var observableData = ko.mapping.fromJS(serverSigners);
var viewModel = new SignerViewModel();
viewModel.signerFields(observableData); // <-- How?
}
I get no error messages, nothing.
There is a lot of unknowns with this one, but here is a working example using the information we have at hand. One thing I noticed was when creating this sample was that I assumed the data comming from Razor was in an array. and when the array is passed into the mapping component it comes out as an observable array. This meant that the data going into the signerFields was probably not what you were expecting and ended up having an observableArray with one object which itself was an observable array. Adding round brackets to observableData() means that you get the data out of the observable and you can then pass it into the signerFields as an array of objects.
Hope that made sense.
function SignerViewModel() {
var self = this;
self.signerFields = ko.observableArray([]);
self.guarantorFields = ko.observableArray([]);
self.companyGuarantorFields = ko.observableArray([]);
}
var serverSigners = [{'fullname':'Test Name', 'lastName': 'Name', 'role': 'Test Role', 'contactInformation': '123 Seasame Street NY, US', 'isCompany': true, 'anySigner': false, 'isInvitation': false}];
var observableData = ko.mapping.fromJS(serverSigners);
var viewModel = new SignerViewModel();
viewModel.signerFields(observableData());
ko.applyBindings(viewModel)
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<div data-bind="foreach: signerFields, visible: signerFields().length > 0">
<div class="row">
<div class="col-lg-10">
<div>
<div class="row" data-bind="visible: isCompany() && !anySigner() && !isInvitation()">
<div class="col-lg-4">
<b>FullName: </b><span data-bind="text: fullname"></span>
</div>
<div class="col-lg-3">
<b>LastName: </b><span data-bind="text: lastName"></span>
</div>
<div class="col-lg-4">
<b>Role: </b><span data-bind="text: role"></span>
</div>
<div class="col-lg-3">
<b>Contact Information: </b><span data-bind="text: contactInformation"></span>
</div>
</div>
</div>
</div>
</div>
</div>

Validation not getting triggered when value is changed

In Aurelia project, I have created a bootstrap modal that will allow users to enter email addresses. At first when the pop-up is triggered, it applies the validation fine. See below image. This is how it looks like when the pop-up is opened for the first time.
Once you enter the validate email address and click on add btn, I am resetting the value of this.setEmail to "" an empty string. So that way users can type new email address to add. But the validation rule that shows the message Email is required is no longer getting triggered. See below example:
See the Plunker link here. Once the page is loaded. Click on the + icon next to email input. It will open a bootstrap modal.
Below is the code and can be seen at above link as well:
email.ts
import { customElement, useView, bindable, bindingMode, inject, observable } from 'aurelia-framework';
import { ValidationRules, ValidationControllerFactory, Validator } from 'aurelia-validation';
#inject(ValidationControllerFactory)
#customElement('email')
#useView('./email.html')
export class Email {
#bindable public modalName: string;
#bindable public modalValue: string;
#bindable public emailAddress: string;
public emailAddresses = [];
#observable public setEmail: string;
public errorMessage: string;
emailController = null;
constructor(factory) {
this.setEmail = '';
this.emailController = factory.createForCurrentScope();
ValidationRules.ensure('setEmail')
.displayName('Email')
.required()
.email()
.on(this);
}
public bind() {
this.emailController.validate();
}
private joinEmails() {
this.emailAddress = this.emailAddresses.join(";");
}
private isUniqueEmail = (email: string) => {
return (this.emailAddresses.indexOf(email) === -1)
}
public addEmail() {
if (this.setEmail) {
if(!this.isUniqueEmail(this.setEmail))
{
this.errorMessage = "You must provide unique email address.";
return;
}
this.emailAddresses.push(this.setEmail);
this.joinEmails();
this.setEmail = '';
}
else
{
this.errorMessage = "You must provide an email address."
}
}
public setEmailChanged(newValue, oldValue) {
console.log({oldValue: oldValue, newValue: newValue});
}
public removeEmail(index) {
this.emailAddresses.splice(index, 1);
this.joinEmails();
console.log(this);
}
}
email.html
<template>
<!-- Modal -->
<div class="modal fade" id="${modalName}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Add Email Address</h4>
</div>
<div class="modal-body">
<div class="input-group">
<input type="text" id="setEmail" name="setEmail" class="form-control" value.bind="setEmail & validateOnChangeOrBlur" />
<span class="input-group-btn">
<button class="btn btn-primary"
disabled.bind="emailController.errors.length > 0"
click.delegate="addEmail()">Add
</button>
</span>
</div>
<input type="text" value.bind="emailAddress" hidden />
<span class="text-danger" repeat.for="error of emailController.errors">${error.message}</span>
<span class="text-danger" if.bind="errorMessage">${errorMessage}</span>
<div>
<ul class="list-group" if.bind="emailAddresses.length > 0" style="margin-top: 10px;">
<li class="list-group-item" repeat.for="e of emailAddresses">
${e} <span class="glyphicon glyphicon-remove text-danger pull-right" style="cursor: pointer;" click.delegate="removeEmail($index)"></span>
</li>
</ul>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</template>
In your addEmail() function after the line this.setEmail = ''; call the validate again with this.emailController.validate();
The validate() method returns a Promise so you may want to handle any rejections as you would normally see this section of the validation docs Validation Controller specifically the sub section 'validate & reset'.
I'm guessing you expected this to happen automatically because of the 2-way binding and the validateOnChangeOrBlur binding behavior the reason it didn't is that the JavaScript setting the value doesn't trigger DOM events so you need to manually call or fire a synthetic event.

Aurelia custom element access data from child to parent view model

I am new to Aurelia and need help accessing values from custom element in another view.
I have a scenario where I would like to share input file for attachment in multiple forms. One of the approach I am taking is to create custom element for input files that can be shared with multiple forms in web application.
Below is my code:
Custom element called FilePicker which will be shared between multiple forms. In my Request paged I inserted the custom element called:
<file-picker router.bind="router" accept="image/*" multiple="true" ></file-picker>
My requirement is to access property called validFiles which is an array. I would like to use values from validFiles to custom object in Request view model called formData['attachment']
TS:
import { customElement, useView, bindable, bindingMode } from 'aurelia-framework';
#customElement('file-picker')
#useView('./file-picker.html')
export class FilePicker {
#bindable accept = '';
#bindable multiple = false;
#bindable({ defaultBindingMode: bindingMode.twoWay }) files: FileList;
validFiles = [];
input: HTMLInputElement;
// Validate function for on change event to input file.
public filesChanged() {
if (!this.files) {
this.clearSelection();
}
if (this.files) {
this.processFiles();
}
}
// Trigger on button click
public triggerInputClick() {
this.input.click();
}
// Find value in array of object
private findValinArrObj(arr, key, val) {
return arr.map(function (v) { return v[key] }).indexOf(val);
}
// Process file for each new files uploaded via browser
private processFiles() {
if (this.files) {
for (let i = 0; i < this.files.length; i++) {
let findFile = this.findValinArrObj(this.validFiles, 'name', this.files.item(i).name);
if (findFile === -1) {
this.validFiles.push(this.files.item(i));
}
}
this.clearSelection();
}
}
// Remove file from fileNames and validFiles array
public removeByFileName(fileName) {
if (this.validFiles) {
for (let i = 0; i < this.validFiles.length; i++) {
if (this.validFiles[i].name === fileName) {
this.validFiles.splice(i, 1);
}
}
}
}
// Clear input file in DOM
private clearSelection() {
this.input.type = '';
this.input.type = 'file';
}
}
HTML:
<template>
<input type="file" accept.bind="accept" multiple.bind="multiple"
files.bind="files" ref="input"
style="visibility: hidden; width: 0; height: 0;">
<button class="btn btn-primary" click.delegate="triggerInputClick()">
<slot>Browse...</slot>
</button>
<ul class="list-group" if.bind="validFiles">
<li class="list-group-item" repeat.for="file of validFiles" style="padding: 0; border:none;">
${file.name} <span class="glyphicon glyphicon-remove text-danger" style="cursor: pointer;" click.delegate="removeByFileName(file.name)"></span>
</li>
</ul>
</template>
Parent View Model:
TS:
export class Request {
pageTitle: string = "Request Page";
title: string = '';
description: string = '';
businessValue: string = '';
emails: string = '';
formData: object = {};
public postData() {
this.formData['title'] = this.title;
this.formData['description'] = this.description;
this.formData['businessValue'] = this.businessValue;
this.formData['emails'] = this.emails;
this.formData['attachment'] = [];
console.log(this.formData);
}
}
HTML:
<template>
<require from="./request.css"></require>
<require from="../../resources/elements/file-picker"></require>
<div class="panel panel-primary">
<div class="panel-heading">${pageTitle}</div>
<div class="panel-body">
<form class="form-horizontal">
<div class="form-group">
<label for="title" class="col-sm-2 control-label">Title</label>
<div class="col-sm-10">
<input type="text" value.two-way="title" class="form-control" id="title" placeholder="Brief one-line summary of the request">
</div>
</div>
<div class="form-group">
<label for="description" class="col-sm-2 control-label">Description</label>
<div class="col-sm-10">
<input type="text" value.two-way="description" class="form-control" id="description" placeholder="Detailed description of the request">
</div>
</div>
<div class="form-group">
<label for="description" class="col-sm-2 control-label">Business Value</label>
<div class="col-sm-10">
<input type="text" value.two-way="businessValue" class="form-control" id="description" placeholder="Description of how this offers business value">
</div>
</div>
<div class="form-group">
<label for="emails" class="col-sm-2 control-label">Email</label>
<div class="col-sm-10">
<input type="text" value.two-way="emails" class="form-control" id="emails" placeholder="Provide email address">
</div>
</div>
<div class="form-group">
<label for="exampleInputFile" class="col-sm-2 control-label">Attachment(s)</label>
<div class="col-sm-10">
<file-picker router.bind="router" accept="image/*" multiple="true" ></file-picker>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="submit" class="btn btn-default pull-right" click.trigger="postData()">Submit</button>
</div>
</div>
</form>
</div>
</div>
</template>
Any help is really appreciated. :)
You can set up two-way-binding on your Request view, to bind the validFiles in your child view (file-picker) to a variable in your parent view (Request):
request.html:
<file-picker valid-files.two-way="validFiles"></file-picker>
request.ts:
public validFiles: File[];
file-picker.ts:
#bindable
public validFiles: File[];
This way any changes made to the validFiles object in either the child or the parent will update the object in both viewmodels.