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.

Learn More, Pay Less
33% OFF
All Trainings!
Get Your Deal
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.0.0-preview. Updated on September 10, 2025, 06:30