Open Closed

How to Extend Organization Units in Angular Ui #8973


User avatar
0
cangunaydin created
  • ABP Framework version: v9.0.x
  • UI Type: Angular
  • Database System: EF Core (PostgreSQL)
  • Tiered (for MVC) or Auth Server Separated (for Angular): yes

Hello, I want to add an extra property to organization units, i have managed to that in the backend with module extension. When i try to extend the angular side it does not seem i have an extension point there.

it seems like i can not extend the organization units when i look at this code.

export type IdentityCreateFormPropContributors = Partial<{
  [eIdentityComponents.Claims]: CreateFormPropContributorCallback<ClaimTypeDto>[];
  [eIdentityComponents.Roles]: CreateFormPropContributorCallback<IdentityRoleDto>[];
  [eIdentityComponents.Users]: CreateFormPropContributorCallback<IdentityUserDto>[];
}>;

here is what i have tried according to documentation https://abp.io/docs/latest/framework/ui/angular/dynamic-form-extensions#step-1-create-form-prop-contributors and here is my code. can you give some suggestions about how can i extend the organization units?


  import { ePropType, FormProp, FormPropList } from '@abp/ng.components/extensible';

import {  OrganizationUnitWithDetailsDto } from '@volo/abp.ng.identity/proxy';
import {
  eIdentityComponents,
  IdentityCreateFormPropContributors
} from '@volo/abp.ng.identity';

  

const shareOfVoiceProp = new FormProp<OrganizationUnitWithDetailsDto>({
    type: ePropType.Number,
    name: 'ShareOfVoice',
    displayName: '::DisplayName:ShareOfVoice'
  });
  
  export function shareOfVoicePropContributor(propList: FormPropList<OrganizationUnitWithDetailsDto>) {
    propList.addByIndex(shareOfVoiceProp, 1);
  }


  export const identityCreateFormPropContributors: IdentityCreateFormPropContributors = {
    // enum indicates the page to add contributors to
    [eIdentityComponents.OrganizationUnits]: [
      shareOfVoicePropContributor
      // You can add more contributors here
    ],
  };
  
  export const identityEditFormPropContributors = identityCreateFormPropContributors;
  // you may define different contributors for edit form if you like```

6 Answer(s)
  • User Avatar
    0
    cangunaydin created

    also one more thing. Whenever i extend the organization units from module extension.

    ConfigureIdentity(saas =>
                {
                    saas.ConfigureOrganizationUnit(ou =>
                    {
                        ou.AddOrUpdateProperty<int?>("ShareOfVoice", property =>
                        {
                            property.Attributes.Add(new RangeAttribute(0, 100));
                            property.UI.OnTable.IsVisible = true;
                            property.UI.OnCreateForm.IsVisible = true;
                            property.UI.OnEditForm.IsVisible = true;
                        });
                    });
                });
    

    RangeAttribute is not following the validation on the backend.

  • User Avatar
    0
    erdem.caygor created
    Support Team

    Hello,

    Thank you for reporting this issue. You can extend the organization unit, but there is a type error that needs to be fixed. We will address this issue in the next patch release. In the meantime, as a workaround, you can add // @ts-ignore at the location where the error occurs. Here is a working example:

    // form-prop-contributors.ts
    
    import { ePropType, FormProp, FormPropList } from '@abp/ng.components/extensible';
    import {
      eIdentityComponents,
      IdentityCreateFormPropContributors,
    } from '@volo/abp.ng.identity';
    import { OrganizationUnitDto } from '@volo/abp.ng.identity/proxy';
    
    
    const shareOfVoiceProp = new FormProp({
      type: ePropType.Number,
      name: 'ShareOfVoice',
      displayName: '::DisplayName:ShareOfVoice'
    });
    
    export function shareOfVoicePropContributor(propList: FormPropList<OrganizationUnitDto>) {
      propList.addByIndex(shareOfVoiceProp, 1);
    }
    
    export const identityCreateFormPropContributors: IdentityCreateFormPropContributors = {
      // enum indicates the page to add contributors to
      // @ts-ignore
      [eIdentityComponents.OrganizationUnits]: [
        shareOfVoicePropContributor
        // You can add more contributors here
      ],
    };
    
    export const identityEditFormPropContributors = identityCreateFormPropContributors;
    // you may define different contributors for edit form if you like```
    
    
     // app-routing.module.ts
      {
        path: 'identity',
        loadChildren: () => import('@volo/abp.ng.identity').then(m =>
          m.IdentityModule.forLazy({
            createFormPropContributors: identityCreateFormPropContributors,
            editFormPropContributors: identityCreateFormPropContributors,
          })
        ),
      },
    

    Also, I am unable to reproduce the RangeAttribute error. Could you please share the POST request body that you are sending?

    Let us know if we can further assist you

  • User Avatar
    0
    cangunaydin created

    here is the payload. i have the abp version 9.0 by the way. do you also use the same version?

  • User Avatar
    0
    erdem.caygor created
    Support Team

    Hello,

    Yes, I have tested this with version 9.0 of ABP. Here is my configuration object and the request body that was successfully saved

               ObjectExtensionManager.Instance.Modules()
                 .ConfigureIdentity(identity =>
                             {
                                 identity.ConfigureOrganizationUnit(ou =>
                                 {
                                     ou.AddOrUpdateProperty<int?>("MaxShareOfVoice", property =>
                                     {
                                         property.Attributes.Add(new RangeAttribute(0, 20));
                                         property.UI.OnTable.IsVisible = true;
                                         property.UI.OnCreateForm.IsVisible = true;
                                         property.UI.OnEditForm.IsVisible = true;
                                     });
                                 });
                             });
    

    I will look into this error and let you know

  • User Avatar
    0
    cangunaydin created

    okay i think i have found the problem but i need a solution for my case. this error happens because i removed JsonSerializer Converters that is type of ObjectToInferredTypesConverter to use IAsyncEnumerable from my controllers.

     private void ConfigureJsonSerializerForAsyncEnumarable(ServiceConfigurationContext context, IConfiguration configuration)
        {
            context.Services.Configure<JsonOptions>(options =>
            {
                options.JsonSerializerOptions.Converters.RemoveAll(x => x.GetType() == typeof(ObjectToInferredTypesConverter));
            });
        }
    

    i need to keep this code since i need to serialize json responses asynchronously from my controller. But this is effecting the validations in extra properties.

    Is there any other way that i can have both of the worlds.

  • User Avatar
    0
    EngincanV created
    Support Team .NET Developer

    okay i think i have found the problem but i need a solution for my case. this error happens because i removed JsonSerializer Converters that is type of ObjectToInferredTypesConverter to use IAsyncEnumerable from my controllers.

     private void ConfigureJsonSerializerForAsyncEnumarable(ServiceConfigurationContext context, IConfiguration configuration) 
        { 
            context.Services.Configure<JsonOptions>(options => 
            { 
                options.JsonSerializerOptions.Converters.RemoveAll(x => x.GetType() == typeof(ObjectToInferredTypesConverter)); 
            }); 
        } 
    

    i need to keep this code since i need to serialize json responses asynchronously from my controller. But this is effecting the validations in extra properties.

    Is there any other way that i can have both of the worlds.

    Hi, you may create a new a custom JsonConverter for IAsyncEnumerable like the below:

    using System;
    using System.Collections.Generic;
    using System.Text.Json;
    using System.Text.Json.Serialization;
    
    namespace YourNamespace;
    
    public class AsyncEnumerableConverter : AsyncEnumerableConverter<object>
    {
        
    }
    
    public class AsyncEnumerableConverter<T> : JsonConverter<IAsyncEnumerable<T>>
    {
        public override IAsyncEnumerable<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            throw new NotSupportedException("Reading IAsyncEnumerable from JSON is not supported.");
        }
    
        public override void Write(Utf8JsonWriter writer, IAsyncEnumerable<T> value, JsonSerializerOptions options)
        {
            writer.WriteStartArray();
            var enumerator = value.GetAsyncEnumerator();
            try
            {
                while (enumerator.MoveNextAsync().GetAwaiter().GetResult())
                {
                    JsonSerializer.Serialize(writer, enumerator.Current, options);
                }
            }
            finally
            {
                enumerator.DisposeAsync().AsTask().GetAwaiter().GetResult();
            }
            writer.WriteEndArray();
        }
    }
    

    Then without removing ObjectToInferredTypesConverter instead add the new jsonconverter by configuring the JsonOptions:

    context.Services.Configure<JsonOptions>(options =>
    {
        options.JsonSerializerOptions.Converters.Add(new AsyncEnumerableConverter());
        // You should NOT have the line that removes ObjectToInferredTypesConverter here anymore
    });
    

    Please let me know, if it fixes your problem or not. Regards.

Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
Do you need assistance from an ABP expert?
Schedule a Meeting
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v9.3.0-preview. Updated on April 16, 2025, 12:13