This is a migrated thread and some comments may be shown as answers.

RadDataForm automatically adds source properties if unused

16 Answers 155 Views
DataForm
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Jonathan Salomon
Top achievements
Rank 1
Jonathan Salomon asked on 30 Apr 2017, 10:39 AM

I see that RadDataForm automatically creates editors for any properties that are not declared as TKEntityProperty. How can I inform RadDataForm to skip a specific property? Just specify everything and use *ngIf="false" or is there a better way like telling it to create only what was specifically defined?

Thanks!

16 Answers, 1 is accepted

Sort by
0
Accepted
Nick Iliev
Telerik team
answered on 01 May 2017, 11:55 AM
Hey Jonathan,

Indeed, any properties passed through source will have their editors automatically created. This was implemented to ease the creation of RadDataForm without having to explicitly write code for TKEntityProperty. In the common cases, we will always know what kind of form we have to provide for our users so the best scenario is to normalize the object passed as a source. 

Using Angular structural directives like *ngIf has the downside to make your code more "heavy" as it will do additional redrawing operation based on the condition.

Still, if you need to change the number of editors runtime you can access the properties of your RadDataForm, but you will still need to normalize the source object.

Here is an example that shows a basic scenario where we change the number of properties runtime.
import { Component, OnInit } from '@angular/core';
import { RadDataForm } from "nativescript-telerik-ui-pro/dataform";
 
@Component({
    template: `
    <GridLayout rows="*, auto">
      <RadDataForm row="0" [source]="credentials" (loaded)="onFormLoaded($event)">
            <TKEntityProperty tkDataFormProperty name="username" displayName="E-Mail" index="0">
                <TKPropertyEditor tkEntityPropertyEditor type="Email"></TKPropertyEditor>
            </TKEntityProperty>
            <TKEntityProperty tkDataFormProperty name="password" displayName="Password" index="1">
                <TKPropertyEditor tkEntityPropertyEditor type="Password"></TKPropertyEditor>
            </TKEntityProperty>
            <TKEntityProperty tkDataFormProperty name="environment" [valuesProvider]="environments" displayName="Environment" index="2">
                <TKPropertyEditor tkEntityPropertyEditor type="Picker"></TKPropertyEditor>
            </TKEntityProperty>
      </RadDataForm>
      <Button row="1" text="Sign in" (tap)="doLogin()" class="btn"></Button>
    </GridLayout>
  `,
    styles: [`
    #container { background-color:#efefef; }
  `]
})
export class DataFormGettingStartedComponent implements OnInit {
    public credentials: any;                      // credentials to pass to backend
    public environments: Array<string> = [];      // environments configured in ConfigProvider
    public selectedEnv: number = 0;               // environment from last successful login
    constructor() {
    }
 
    public ngOnInit() {
        this.credentials = {
            "username": "",
            "password": "",
            "environment": "",
            "someProp": "" // new property introduced for which we do not want editor to be created
        };
    }
 
    public onFormLoaded(args) {
        var radDataForm = <RadDataForm>args.object;
 
        console.log(radDataForm.properties[3].name); // someProp
        radDataForm.properties.pop(); // remove the last prop but we also have splice, slice, etc.
 
        console.log(radDataForm.properties) // now the properties are 3 but we still need to edit the source object before reloading the whole form
 
        // normilizing the source object
        radDataForm.source = {
            "username": "",
            "password": "",
            "environment": ""
        };
 
        radDataForm.reload();
    }
}

In other cases, we might want only change the editor of our automatically loaded property and you can achieve that by accessing the editor  of the property for change
public changeEditor() {
    var property = myDataForm.getPropertyByName("age");
    var propertyEditor = new PropertyEditor();
    propertyEditor.type = "Email";
    property.editor = propertyEditor;
}



Regards,
Nikolay Iliev
Telerik by Progress
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Jonathan Salomon
Top achievements
Rank 1
answered on 01 May 2017, 03:55 PM

Since I do not control the backend and the JSON data it returns can change, I guess in my case it will be best to build a custom object based on a whitelist instead of blacklist approach.

Thanks Nikolay!

 

0
Jonathan Salomon
Top achievements
Rank 1
answered on 01 May 2017, 09:19 PM

Hi Nokilay,

I am trying to use your example above where you use the (loaded) event to reload data after it is updated by the backend. However, where radDataForm.reload indeed is a function that can be called, the radDataForm.source is undefined. From your example and also from the docs I would expect it to be an object?

When this is called on the (loaded) event:

public onFormLoaded(args) {
    var radDataForm = <RadDataForm>args.object;
    console.log('radDataForm.reload: '+ typeof radDataForm.reload);
    console.log('radDataForm.source: '+ typeof radDataForm.source);
}

 

It will display this output:

CONSOLE LOG file:///app/components/test-run-form.js:79:20: radDataForm.reload: function
CONSOLE LOG file:///app/components/test-run-form.js:80:20: radDataForm.source: undefined

 

So how can I overwrite the source after it has been loaded?

Thanks!

0
Nick Iliev
Telerik team
answered on 02 May 2017, 08:50 AM
Hey Jonathan,

Thank you for reporting back to us this one! I have made some research, and it appears that the issue here is related your RadDataForm reference in the loaded event (args.object). I was testing this case with app where the Angular version used is 2.4.x, and my example worked as expected. In the same time, I am guessing that you are using the newer version of Angular that comes from our angular template project (where the version used is 4.x.x) and it appears that due to some changes in how Angular works with the components now you are getting not reference to RadDataForm but ProxyViewContainer. 
This is unwanted behavior, and  I have logged this one as a bug here. Our developers are currently looking into it and once we have a possible solution and fix the information will be updated.

Once again I am sorry for any inconvenience this might have caused you!
As a temporary workaround, you can use the version dependencies used here in your project, and you should be able to get the expected reference to RadDataForm and from there to have access to the properties if the form.

Regards,
Nikolay Iliev
Telerik by Progress
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Nick Iliev
Telerik team
answered on 02 May 2017, 10:05 AM
Hi again Jonathan,

Just for your information, I wanted to inform you that the fix is already included in the RC version of nativescript-telerik-ui-pro and will be included in the next official release.

Meanwhile, you can test the RC versions but keep in mind that it is not backward compatible with NativeScript 2.5.x and also uses the RC versions of NativeScript CLUI, runtimes, and modules.
For your convenience, I have created this project working with all the RC versions. In the project, the code used in my snippet works as expected and you can get a reference to your RadDataForm as described.

Regards,
Nikolay Iliev
Telerik by Progress
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Jonathan Salomon
Top achievements
Rank 1
answered on 02 May 2017, 03:26 PM

Hi Nokilay,

Thanks for checking it out, but actually I am using angular 2.4.6. Please see my package.json below. Do you still think it is the same issue? I also tried to use a reference through ViewChild but it did not work for me either.

{
  "description": "<description>",
  "license": "SEE LICENSE IN LICENSE",
  "readme": "NativeScript Application",
  "repository": "<repo>",
  "nativescript": {
    "id": "com.abhayastudios.testapp",
    "tns-android": {
      "version": "2.5.0"
    },
    "tns-ios": {
      "version": "2.5.0"
    }
  },
  "dependencies": {
    "@angular/common": "2.4.6",
    "@angular/compiler": "2.4.6",
    "@angular/core": "2.4.6",
    "@angular/forms": "2.4.6",
    "@angular/http": "2.4.6",
    "@angular/platform-browser": "2.4.6",
    "@angular/platform-browser-dynamic": "2.4.6",
    "@angular/router": "3.4.6",
    "nativescript-angular": "1.4.1",
    "nativescript-telerik-ui-pro": "file:./nativescript-ui-pro/nativescript-ui-pro.tgz",
    "nativescript-theme-core": "~1.0.2",
    "nativescript-toasts": "^1.0.2",
    "reflect-metadata": "~0.1.8",
    "rxjs": "~5.0.1",
    "tns-core-modules": "^2.5.2"
  },
  "devDependencies": {
    "@angular/compiler-cli": "2.4.6",
    "@ngtools/webpack": "1.2.10",
    "babel-traverse": "6.22.1",
    "babel-types": "6.22.0",
    "babylon": "6.15.0",
    "copy-webpack-plugin": "~4.0.1",
    "extract-text-webpack-plugin": "~2.1.0",
    "htmlparser2": "~3.9.2",
    "lazy": "1.0.11",
    "nativescript-css-loader": "~0.26.0",
    "nativescript-dev-android-snapshot": "^0.*.*",
    "nativescript-dev-typescript": "~0.3.5",
    "nativescript-dev-webpack": "^0.4.0",
    "raw-loader": "~0.5.1",
    "resolve-url-loader": "~2.0.2",
    "typescript": "~2.1.6",
    "webpack": "~2.3.3",
    "webpack-sources": "~0.2.3",
    "zone.js": "~0.7.2"
  },
  "scripts": {
    "ns-bundle": "ns-bundle",
    "start-android-bundle": "npm run ns-bundle --android --start-app",
    "start-ios-bundle": "npm run ns-bundle --ios --start-app",
    "build-android-bundle": "npm run ns-bundle --android --build-app",
    "build-ios-bundle": "npm run ns-bundle --ios --build-app"
  }
}
0
Jonathan Salomon
Top achievements
Rank 1
answered on 02 May 2017, 03:31 PM
How difficult will it be to patch the UI-Pro v1.6.1?
0
Nick Iliev
Telerik team
answered on 03 May 2017, 06:21 AM
Hey Jonathan,

You can also use these techniques with v1.6.1, in fact, I was testing with this exact version at first. However, in this case, you will need to adjust the versions of your angular wrapper (nativescript-angular) and to your Angular related dependencies. The easiest approach would be to use this package.json as reference

You can also clone the whole application.and test my snippet with replacing the code in some of the examples - I personally used this one (that is the reason for the component to be called as the original - DataFormGettingsStartedComponent). So if you use the compatible versions you will be able to get your references via loaded event, ViewChild directive or even via Page instance in the constructor and then getViewById w/NativeScript ID

Regards,
Nikolay Iliev
Telerik by Progress
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Jonathan Salomon
Top achievements
Rank 1
answered on 03 May 2017, 12:47 PM

Hi Nikolay,

I did what you said but unfortunately also with Angular 2.4.3 and the 1.4.0 version of the wrapper the reference thing is still not working. I solved my problem, however, without needing any reference. In my case, I just wanted to update the form to use source data from async backend. So I did it by making sure the variable holding the source object gets a new reference, thus forcing angular to do a change detection: this.step= Object.assign({}, this.step);

Thanks for all your help!

P.S.

I created a small test app to check the issue, let me know if you want me to share it to github (in case you want to see the problem with the reference).

 

0
Nick Iliev
Telerik team
answered on 03 May 2017, 01:00 PM
Hey Jonathan,

Glad to hear that you were able to resolve your issue! 

Regarding the test application, you have created - indeed it will be of help so I could further investigate this case. You can share it with me here when you have spare time. Thank you in advance!

Regards,
Nikolay Iliev
Telerik by Progress
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Jonathan Salomon
Top achievements
Rank 1
answered on 03 May 2017, 01:12 PM

Sure you can find it here: https://github.com/abhayastudios/testapp

Look at: app/components/form.ts

0
Nick Iliev
Telerik team
answered on 03 May 2017, 01:41 PM
Hey Jonathan,

Thank you for the follow-up!
I will look into it  and report back once I have more insights.

Regards,
Nikolay Iliev
Telerik by Progress
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Nick Iliev
Telerik team
answered on 03 May 2017, 02:28 PM
Hey Jonathan,

FYI: I had some time to play around with the test application and found the reason for you not to be able to get a reference to your source in onFormLoaded.
here is what is happening step by step.
- the first place where you are getting a reference to your RadDataForm layout is at this line. However, at this point, the source is not yet set so it is undefined.
- then the ngOnInit is triggered and this.radDataForm.source  is generated by your simulated API call (in the method which on the other hand has setTimeOut for 5 seconds to simulate an API call). Only then the source is set and is no longer undefined but of type [object Object].

Example based on your test application:
ngOnInit(): void {
    this.getDataFromBackend(); // the simulated API call here is the one setting the source for the first time
 
    console.log("ngOnInit radaDataForm: " + this.radDataForm)
    console.log('ngOnInit source: ' + this.radDataForm.source); // the source is already set here
}
 
public onFormLoaded(args) {
    this.radDataForm = <RadDataForm>args.object;
 
             console.log("onFormLoaded radaDataForm: " this.radDataForm)
    console.log('onFormLoaded source: ' + this.radDataForm.source);  // this would be undefined
}

So you can either proceed with the solution you have already reached or change the order of your code execution so that it will assign the source of your RadDataForm before the first reference to it.

Regards,
Nikolay Iliev
Telerik by Progress
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Jonathan Salomon
Top achievements
Rank 1
answered on 03 May 2017, 02:35 PM
Thanks but shouldn't the source be set on initialization by: [source]="step"? Once the loaded event hits, I would expect args.object.source to contain a copy/reference to this.step. In any case, even after calling reload it doesn't update the form (without changing the reference to this.step).
0
Nick Iliev
Telerik team
answered on 03 May 2017, 02:51 PM
Hey Jonathan,

You are absolutely right! It seems that binding to the source is working but at the same time, you have to explicitly set the source via this.radDataForm.source in order to get a reference to the object that is passed as a source. I will get back to you once I have more info why is this happening.

Regards,
Nikolay Iliev
Telerik by Progress
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Jonathan Salomon
Top achievements
Rank 1
answered on 03 May 2017, 02:57 PM

Well no rush, I have working what I needed :)

I guess this would be a good time to tell you guys that I am really happy with UI Pro in general and also that I am very happy with the Data Form addition! It makes it really easy to create good looking forms without a designer :)

Thanks for all your help!

Tags
DataForm
Asked by
Jonathan Salomon
Top achievements
Rank 1
Answers by
Nick Iliev
Telerik team
Jonathan Salomon
Top achievements
Rank 1
Share this question
or