RadDataForm automatically adds source properties if unused

Thread is closed for posting
17 posts, 1 answers
  1. Jonathan Salomon
    Jonathan Salomon avatar
    27 posts
    Member since:
    Oct 2016

    Posted 30 Apr 2017 Link to this post

    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!

  2. Answer
    Nikolay Iliev
    Admin
    Nikolay Iliev avatar
    351 posts

    Posted 01 May 2017 Link to this post

    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.
  3. Jonathan Salomon
    Jonathan Salomon avatar
    27 posts
    Member since:
    Oct 2016

    Posted 01 May 2017 in reply to Nikolay Iliev Link to this post

    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!

     

  4. Jonathan Salomon
    Jonathan Salomon avatar
    27 posts
    Member since:
    Oct 2016

    Posted 01 May 2017 in reply to Jonathan Salomon Link to this post

    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!

  5. Nikolay Iliev
    Admin
    Nikolay Iliev avatar
    351 posts

    Posted 02 May 2017 Link to this post

    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 nativescript-ui-sample-angular 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.
  6. Nikolay Iliev
    Admin
    Nikolay Iliev avatar
    351 posts

    Posted 02 May 2017 Link to this post

    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.
  7. Jonathan Salomon
    Jonathan Salomon avatar
    27 posts
    Member since:
    Oct 2016

    Posted 02 May 2017 in reply to Nikolay Iliev Link to this post

    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"
      }
    }
  8. Jonathan Salomon
    Jonathan Salomon avatar
    27 posts
    Member since:
    Oct 2016

    Posted 02 May 2017 in reply to Jonathan Salomon Link to this post

    How difficult will it be to patch the UI-Pro v1.6.1?
  9. Nikolay Iliev
    Admin
    Nikolay Iliev avatar
    351 posts

    Posted 03 May 2017 Link to this post

    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.
  10. Jonathan Salomon
    Jonathan Salomon avatar
    27 posts
    Member since:
    Oct 2016

    Posted 03 May 2017 in reply to Nikolay Iliev Link to this post

    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).

     

  11. Nikolay Iliev
    Admin
    Nikolay Iliev avatar
    351 posts

    Posted 03 May 2017 Link to this post

    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.
  12. Jonathan Salomon
    Jonathan Salomon avatar
    27 posts
    Member since:
    Oct 2016

    Posted 03 May 2017 in reply to Nikolay Iliev Link to this post

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

    Look at: app/components/form.ts

  13. Nikolay Iliev
    Admin
    Nikolay Iliev avatar
    351 posts

    Posted 03 May 2017 Link to this post

    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.
  14. Nikolay Iliev
    Admin
    Nikolay Iliev avatar
    351 posts

    Posted 03 May 2017 Link to this post

    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.
  15. Jonathan Salomon
    Jonathan Salomon avatar
    27 posts
    Member since:
    Oct 2016

    Posted 03 May 2017 in reply to Nikolay Iliev Link to this post

    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).
  16. Nikolay Iliev
    Admin
    Nikolay Iliev avatar
    351 posts

    Posted 03 May 2017 Link to this post

    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.
  17. Jonathan Salomon
    Jonathan Salomon avatar
    27 posts
    Member since:
    Oct 2016

    Posted 03 May 2017 in reply to Nikolay Iliev Link to this post

    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!

Back to Top