Редактирование отдельной записи через контроллер сервера

Добрый день. Помогите пожалуйста разобраться. Имеется таблица с записями, в последней колонке каждой записи есть кнопка. После нажатия на кнопку, должно появится окошко с полями объекта, которые нужно изменить. Окошко я создал. Как передать туда значения полей из записи для дальнейшего редактирования?

Добавьте свой код к вопросу пожалуйста.

Если вы создали решения, пожалуйста поделитесь им со всеми. Заранее спасибо.

2 Likes
    <aura:component implements="flexipage:availableForRecordHome, force:hasRecordId" controller="ProductTableCmpController" access="global">
    <aura:handler name="init" value="{!this}" action="{!c.init}"  />
    <aura:attribute name="productList" type="List" />
     <aura:attribute name="product" type="ProductTable__c"
                    default="{
                             'SObjectType': 'ProductTable__c',
                             'Name': '',
                             'Quantity__c': '',
                             'Price__c': ''
                             }">   
     </aura:attribute> 
    <table class="slds-table slds-table_cell-buffer slds-table_bordered">
        <thead>
          <tr class="slds-line-height_reset">
                
                <th class="slds-text-title_caps" scope="col">
                    <div class="slds-truncate" title="Name">Name</div>
                </th>
                <th class="slds-text-title_caps" scope="col">
                    <div class="slds-truncate" title="Quantity">Quantity</div>
                </th>
                <th class="slds-text-title_caps" scope="col">
                    <div class="slds-truncate" title="Price">Price</div>
                </th>
            </tr>
        </thead>
        <tbody>
            <aura:iteration items="{!v.productList}"  var="prod">
                <tr class="slds-hint-parent">  
                    <td data-label="Name">
                        <div class="slds-truncate" title="Name">{!prod.Name}</div>
                    </td>
                    <td data-label="Quantity">
                        <div class="slds-truncate" title="Quantity">{!prod.Quantity__c}</div>
                    </td>
                    <td data-label="Price">
                        <div class="slds-truncate" title="Price">{!prod.Price__c}</div>
                    </td>
                    <td data-label="Edit">
                        <div class="slds-truncate" title="Edit">
                            <lightning:button label="Edit" name="edit" aura:id="editProduct" onclick="{!c.openModaledit}" iconName="utility:edit_form" />
                        </div>
                    </td>
                </tr>
            </aura:iteration>
        </tbody>
    </table>
    
    <div class="slds-m-around_xx-large">
        <section aura:id="productEditModal" role="dialog" tabindex="-1" aria-labelledby="productModalHeading" aria-modal="true" aria-describedby="contactModalBody" class="slds-modal">
            <div class="slds-modal__container">
                <header class="slds-modal__header">
                    <lightning:buttonIcon class="slds-modal__close" alternativeText="Close" iconName="utility:close" onclick="{!c.closeModaledit}" variant="bare-inverse" size="large"></lightning:buttonIcon>
                    <h2 id="productModalHeading" class="slds-text-heading_medium slds-hyphenate">Edit Product</h2>
                </header>
                <div class="slds-modal__content slds-p-around_medium" id="productModalBody">
                    <lightning:input label="Name" value="{!v.product.Name}" required="true" />
                    <lightning:input type="number"  label="Quantity" value="{!v.product.Quantity__c}" />
                    <lightning:input type="number"  label="Price" value="{!v.product.Price__c}"  />
                </div>
                <footer class="slds-modal__footer">
                    <lightning:button onclick="{!c.closeModaledit}" variant="neutral">Cancel</lightning:button>
                    <lightning:button onclick="{!c.editProduct}" variant="brand" >Save</lightning:button>
                </footer>
            </div>
        </section>
        <div aura:id="productEditModalBackdrop" class="slds-backdrop"></div>
    </div >
</aura:component>
    ({
    init : function(component, event, helper) {
        helper.getdata(component, event, helper);
    },
    openModaledit: function(component, event, helper) {
        helper.modaleditOpen(component, event, helper);
    },
    closeModaledit: function(component, event, helper) {
        helper.modaleditClose(component, event, helper);
    },
    editProduct: function(component, event, helper) {
        helper.productEdit(component, event, helper);
        helper.getdata(component, event, helper);
    },
})
    ({
    getdata: function(component, event, helper) {
        var action = component.get("c.getProducts");
        var accountId = component.get("v.recordId");
        action.setParams({
            accountIds: accountId
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if(state === 'SUCCESS') {
                var Listproducts = response.getReturnValue();
                component.set("v.productList", Listproducts);
            }
            else {
                alert('Error in getting data');
            }
        });
        $A.enqueueAction(action);
    },
    modaleditOpen: function(component, event, helper) {
        var modal = component.find("productEditModal");
        var modalBackdrop = component.find("productEditModalBackdrop");
        $A.util.addClass(modal,"slds-fade-in-open");
        $A.util.addClass(modalBackdrop,"slds-backdrop slds-backdrop_open");
    },
    modaleditClose: function(component, event, helper) {
        var modal = component.find("productEditModal");
        var modalBackdrop = component.find("productEditModalBackdrop");
        $A.util.removeClass(modal,"slds-fade-in-open");
        $A.util.removeClass(modalBackdrop,"slds-backdrop_open");
    },
    productEdit: function(component, event, helper) {
        
    },
})
    public class ProductTableCmpController {
    @AuraEnabled
    public static List<ProductTable__c> getProducts () {
        List<ProductTable__c> Listproducts =
            [SELECT Id, Name, Price__c, Quantity__c FROM ProductTable__c];
        return Listproducts;
    }
    @AuraEnabled
    public static Map<String,String>  updateNewProductTable (List<ProductTable__c> contactList) {
        Map<String,String> resultMap = new Map<String,String>();
        update contactList;
        return resultMap;
    }
}

Можно попробовать:
в самом компоненте, для кнопки (вместо кнопки):

<div id={!prod.Id} class="divAsButton_Style" data-quantity="{!prod.Quantity__c}" data-price="{!prod.Price__c}" ..... onclick="{!c.openModaledit}">

В функции “onclick”:

modaleditOpen: function(component, event, helper) {
.........
    var component_target = event.currentTarget;
    var quantity = component_target.dataset.quantity;
    var price = component_target.dataset.price;
.........
}

Спасибо, но у меня это не сработало.

А можно увидеть функцию?

modaleditOpen: function(component, event, helper) {
    var modal = component.find("productEditModal");
    var modalBackdrop = component.find("productEditModalBackdrop");
    var component_target = event.currentTarget;
    var quantity = component_target.dataset.quantity;
    var price = component_target.dataset.price;      
    $A.util.addClass(modal,"slds-fade-in-open");
    $A.util.addClass(modalBackdrop,"slds-backdrop slds-backdrop_open");
},

Можно добавить в самом компоненте (модальное окно):

<aura:attribute name="quantity" type="String"/>
<aura:attribute name="price" type="String"/>

А в методе:

var modal = component.find("productEditModal");
var component_target = event.currentTarget;
var quantity = component_target.dataset.quantity;
var price = component_target.dataset.price;
modal.set("v.quantity", quantity);
modal.set("v.price", price);

var modal = component.find(“productEditModal”); - получение референса на компонент
modal.set(“v.quantity”, quantity); - установка атрибутов компонента из JS функции
В самом компоненте отобразить необходимые атрибуты на UI.

1 Like

Дока по работе с атрибутами:

Привет,

Можно попробовать lightning:datatable - https://developer.salesforce.com/docs/component-library/bundle/lightning:datatable/example#lightningcomponentdemo:exampleDatatableDynamicRowActions

Для модального окна lightning:overlayLibrary -https://developer.salesforce.com/docs/component-library/bundle/lightning:overlayLibrary/documentation.

        <lightning:datatable
            columns="{! v.columns }"
            data="{! v.productList}"
            keyField="id"
            onrowaction="{! c.handleRowAction }"
           />
4 Likes

Спасибо, но изменения должны вносится через контроллер сервера.

Не вижу противоречий. Конечно они будут вносится через контроллер сервера. Вот пример js контроллера:

({
  init: function(component, event, helper){
      
     var actions = [{label: 'Edit' , name : 'edit' }];
      var columns = [ 
                            { label: 'Name', fieldName: 'name', type: 'text' },
                            { label: 'Quantity', fieldName: 'quantity__c', type: 'text' },
                            { label: 'Price', fieldName: 'price__c', type: 'text' },
                            {type : 'action', typeAttributes : {rowActions : actions}}
                ];
      component.set('v.columns ', columns );
  },
  handleRowAction : function(component, event, helper) {
         var action = event.getParam('action');
         var row = event.getParam('row');
         var productList = component.get('v.productList');
         switch (action.name) {
              case 'edit': 
                       //показываем модальное окно
                      helper.edit(row);
                       break;
         }
  },
})

Спасибо конечно, но этот вариант мне не подходит. мне нужна помощь в том, как значения записи вставить в поля моего модального окна (т.е таблица и модальное окно остаются).

Хорошо, хотя SF рекомендует использовать готовые lightning компоненты как performance best practice : https://developer.salesforce.com/blogs/developer-relations/2017/04/lightning-components-performance-best-practices.html#base_components

Тем не менее, если использовать подход с html table:

  1. В модальном окне используется product, например здесь:
<div class="slds-modal__content slds-p-around_medium" id="productModalBody"> <lightning:input label="Name" value="{!v.product.Name}" required="true" />
<lightning:input type="number" label="Quantity" value="{!v.product.Quantity__c}" /> <lightning:input type="number" label="Price" value="{!v.product.Price__c}" /> </div>

Но самого аттрибута product в компоненте нет. Есть только productList, или я что-то пропустила?

<aura:attribute name="product" type="Product__c" />
  1. Показывая модальное окно, не просто добавляем стиль но и устанавливаем редактируемый продукт:
var product = {Quantity__c: quantity, Price__c: price, Id: id} // Тут обязательно нужен Id - иначе как server-side контроеллер узнает чего обновлять?
component.set('v.product', product);
2 Likes

Да, извиняюсь, атрибут пропустил. В вашем коде quantity, price и id не находит. Их тоже нужно через переменную определять?

Их можно попробовать получить как советовал dmitriy.shestakov.

Второй путь добавляем value атрибут к кнопке. Вот так в цикле:

 <lightning:button label="Edit" name="edit" aura:id="editProduct" onclick="{!c.openModaledit}" iconName="utility:edit_form" value="{!prod}"/>

В таком случае в modaleditOpen нужно будет сделать следующее:

...
var product = event.getSource().get('v.value');
component.set('v.product', product );
....

Вопрос в том, что согласно доке value - это строка, а мы ему отдаем объект. Но у меня так сработало.
https://developer.salesforce.com/docs/component-library/bundle/lightning:button/specification

3 Likes