Base solution for your next web application
Open Closed

Multilingual Property Edit NonModal #12435


User avatar
0
ncvitanovic created

MVC JQuery NonModal:

Editing the property removes all translations. How to fix that?

Markdown is supported
Copy & paste or drag & drop images (max 30 MB per image)

15 Answer(s)
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @ncvitanovic

    Could you share the content of the Update method found in the related entity's App Service with us? Normally, it clears the Translations coming from the database and then maps the values from the input.

    Could you please share with us the input content of the CreateOrEdit method so that we can reproduce the problem?

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    ncvitanovic created
    I have the latest template as well as 4.6.2. asp power tools:
    
    [AbpAuthorize(AppPermissions.Pages_Properties_Create)]
    protected virtual async Task Create(CreateOrEditPropertyDto input)
    {
        var property = ObjectMapper.Map<Property>(input);
    
        if (AbpSession.TenantId != null)
        {
            property.TenantId = (int)AbpSession.TenantId;
        }
    
        await _propertyRepository.InsertAsync(property);
    
    }
    
    [AbpAuthorize(AppPermissions.Pages_Properties_Edit)]
    protected virtual async Task Update(CreateOrEditPropertyDto input)
    {
        var property = await _propertyRepository
            .GetAllIncluding(x => x.Translations)
            .FirstOrDefaultAsync(x => x.Id == (int)input.Id);
    
       property.Translations.Clear();
    
        ObjectMapper.Map(input, property);
    }
    
    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @ncvitanovic

    As shown in the screenshot, what are the input values ​​for the CreateOrEdit method? Similarly, what are the input values ​​for the Update method? I think the reason why other languages ​​are deleted after editing here is that the multilingual property values ​​in the Translations list coming to the CreateOrEdit method are empty. Can you share with us what values ​​are coming here? Thank you.

    If the multilingual property is null here, you can run the "npm run create-bundles" command in your MVC project and test again.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    ncvitanovic created

    Now I am not at the computer. Creating was working. If I edit and change multilingual property it is working. The only thing when I don't change it and just click save it. Then it removes it. Other properties are fine

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    ncvitanovic created

    I tried npm run create-bundles but same error.

    When I enter some value for Name it is ok:

    After I click update. And save without changing Name or any property:

    And then I get nothing for Name.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @ncvitanovic

    As shown in the code snippet below, this is the content of the "CreateOrEdit" method. In this context, does the "RemoveAll" method in the corresponding part of your project include the condition "x.Description.IsNullOrEmpty()"?

    Please note that the "Description" field represents a multilingual property. If this condition is not present, could you please add it appropriately based on your entity and check whether it resolves the issue?

    public virtual async Task CreateOrEdit(CreateOrEditCategoryDto input)
    {
        input.Translations.RemoveAll(x => true && x.Description.IsNullOrEmpty()); //Descripton = Multilingual Property
    
        if (input.Id == null)
        {
            await Create(input);
        }
        else
        {
            await Update(input);
        }
    }
    
    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    ncvitanovic created

    Yes, I do have: input.Translations.RemoveAll(x => true && x.Name.IsNullOrEmpty());

    There are no NullsOrEmpty, so this is not removing anything.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    ncvitanovic created

    The thing is that the entity is FullAudited. If I go to just the Entity, then it works. How to make it working for FullAudited?

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    ncvitanovic created

    I downgraded only TranslationTables to AuditedEntity, and it is ok now.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @ncvitanovic

    In an entity inheriting from the FullAuditedEntity class, the "property.Translations.Clear();" operation is perceived as "IsDeleted=true". Here, you can update the Update method for the entity inheriting from FullAuditedEntity as shown below. This change will not delete the related data from the Translations table when the entity is updated. If you do not need the SoftDelete logic in Audity, you can inherit from the AuditedEntity class and thus you will not need to make any changes for the Update method.

    [AbpAuthorize(AppPermissions.Pages_Property_Edit)]
    protected virtual async Task Update(CreateOrEditPropertyDto input)
    {
        var property = await _propertyRepository
                .GetAllIncluding(x => x.Translations)
                .FirstOrDefaultAsync(x => x.Id == (int)input.Id);
    
        foreach (var inputTranslation in input.Translations)
        {
            var existingTranslation = property.Translations
                .FirstOrDefault(t => t.Language == inputTranslation.Language);
    
            if (existingTranslation != null)
            {
                existingTranslation.Name = inputTranslation.Name;
            }
            else
            {
                property.Translations.Add(new PropertyTranslation
                {
                    Name = inputTranslation.Name,
                    Language = inputTranslation.Language,
                    CoreId = property.Id,
                    TenantId = property.TenantId
                });
            }
        }
    }
    
    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    ncvitanovic created

    Only the multilingual property is updated with your code, but not the other properties, because you are missing: ObjectMapper.Map(input, property); This is again deleting it.

    I can use AuditedEntity for Translation. FullAudited is the Entity. I need the Entity to be fully audited. Translation is ok, not to have SoftDelete.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @ncvitanovic

    Yes, you can use the method below for this scenario. In this way, you can use FullAuditedEntity if you want. Other features will be updated except for the Translations feature.

    Exclude Translations from Mapping

    When using ObjectMapper, we can exclude the Translations collection from the mapping process. This prevents the existing translations from being marked as IsDeleted = true. We achieve this by defining a custom AutoMapper profile and ignoring the Translations property.

    You can add the map setting to the CreateMappings static method in the CustomDtoMapper class as specified below.

    public static void CreateMappings(IMapperConfigurationExpression configuration)
    {
        configuration.CreateMap<CreateOrEditPropertyDto, Property>()
            .ForMember(dest => dest.Translations, opt => opt.Ignore());
        
        //...
    }
    
    
    [AbpAuthorize(AppPermissions.Pages_Property_Edit)]
    protected virtual async Task Update(CreateOrEditPropertyDto input)
    {
        var property = await _propertyRepository
            .GetAllIncluding(x => x.Translations)
            .FirstOrDefaultAsync(x => x.Id == (int)input.Id);
    
        ObjectMapper.Map(input, property); // Updates other fields, excludes Translations
    
        foreach (var inputTranslation in input.Translations)
        {
            var existingTranslation = property.Translations
                .FirstOrDefault(t => t.Language == inputTranslation.Language);
    
            if (existingTranslation != null)
            {
                existingTranslation.Name = inputTranslation.Name;
            }
            else
            {
                property.Translations.Add(new PropertyTranslation
                {
                    Name = inputTranslation.Name,
                    Language = inputTranslation.Language,
                    CoreId = property.Id,
                    TenantId = property.TenantId
                });
        }
    }
    

    This way, the main Property entity fields are updated using ObjectMapper, and the Translations collection is handled manually to avoid triggering soft delete logic.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    ncvitanovic created

    I also changed to make it work for Create. Maybe you know something better.

        configuration.CreateMap&lt;CreateOrEditPropertyDto, Property&gt;()
            .ForMember(dest => dest.Translations, opt => opt.Ignore());
        configuration.CreateMap&lt;Property, CreateOrEditPropertyDto&gt;();
        //configuration.CreateMap&lt;CreateOrEditPropertyDto, Property&gt;().ReverseMap(); --THIS IS REMOVED
    
    [AbpAuthorize(AppPermissions.Pages_Properties_Create)]
    protected virtual async Task Create(CreateOrEditPropertyDto input)
    {
        var property = ObjectMapper.Map&lt;Property&gt;(input);
    
        if (input.Translations != null)
        {
            property.Translations = [];
    
            foreach (var inputTranslation in input.Translations)
            {
                property.Translations.Add(new PropertyTranslation
                {
                    Name = inputTranslation.Name,
                    Language = inputTranslation.Language,
                    CoreId = property.Id,
                    TenantId = property.TenantId
                });
            }
        }
    
        if (AbpSession.TenantId == null) return;
        
        property.TenantId = (int)AbpSession.TenantId;
        
        await _propertyRepository.InsertAsync(property);
    }
    
    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @ncvitanovic

    Yes, you can use it like this. Maybe you can define it as a list while defining "property.Translations". You can also define TenantId before defining Translations. And to define Translations CoreId, you need to add Property first and then Translations. You can use the code snippet below.

    [AbpAuthorize(AppPermissions.Pages_Properties_Create)]
    protected virtual async Task Create(CreateOrEditPropertyDto input)
    {
        var property = ObjectMapper.Map<Property>(input);
    
        if (AbpSession.TenantId != null)
        {
            property.TenantId = (int)AbpSession.TenantId;
        }
    
        var propertyId = await _propertyRepository.InsertAndGetIdAsync(property);
    
        if (input.Translations != null && input.Translations.Any())
        {
            foreach (var inputTranslation in input.Translations)
            {
                var translation = new PropertyTranslation
                {
                    Name = inputTranslation.Name,
                    Language = inputTranslation.Language,
                    CoreId = propertyId,
                    TenantId = property.TenantId
                };
    
                await _propertyTranslationRepository.InsertAsync(translation);
            }
        }
    }
    
    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    ncvitanovic created

    Thank you!

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)