Create Account-Asset Record-Specific Action in Lightning Component

To create Account-Asset record-specific action in Lightning Component, you must add the force:hasRecordId interface to the Aura component to enable the component to be assigned the ID of the current record. The current record ID is useful if the component is used on a Lightning record page, as an object-specific custom action or action override in Lightning Experience or the Salesforce app. force:hasRecordId is a marker interface, that is, a signal to the component’s container to add the interface’s behavior to the component.
Note that the recordId attribute is set only when you place or invoke the component in an explicit record context. For example, when you place the component directly on a record page layout, or invoke it as an object-specific action from a record page or object home.

Lightning component actions are custom actions that invoke a Lightning component. They support Apex and JavaScript and provide a secure way to build client-side custom functionality. Remember that Lightning component actions are supported only in the Salesforce mobile app and Lightning Experience.

For a component to work as a Lightning component action, it must implement either the force:LightningQuickAction or
force:LightningQuickActionWithoutHeader interfaces. You must set a default value for every component attribute marked as required.

Components used as actions that implement the force:lightningQuickAction interface display in a panel with standard action controls. However, if you want complete control over the user interface, use the force:lightningQuickActionWithoutHeader interface. Components that implement force:lightningQuickActionWithoutHeader display in a panel without additional controls and are expected to provide a complete user interface for the action.

Note: Components can implement either the force:lightningQuickAction interface or the force:lightningQuickActionWithoutHeader interface, but not both.

To create Account-Asset record-specific action in Lightning Component, consider this example:

The Component – AccountAssetAction.cmp

<aura:component controller="AccountAssetAction"
implements="force:lightningQuickActionWithoutHeader,force:hasRecordId">
    <aura:attribute name="account" type="Account"/>
    <aura:attribute name="newAsset" type="Asset" default="{ 'sobjectType': 'Asset' }"/>
    
  <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>   
    <div class="slds-page-header" role="banner">
    <p class="slds-text-heading_label">{!v.account.Name}</p>
    <h1 class="slds-page-header__title slds-m-right_small
    slds-truncate slds-align-left">Create New Asset</h1>
    </div>
   
    <lightning:input aura:id="assetField" name="Name" label="Asset Name"
    value="{!v.newAsset.Name}" required="true"/>
   <lightning:input aura:id="assetField" name="serialNumber" label="Serial Number" value="{!v.newAsset.SerialNumber}" required="true"/>
    <lightning:input aura:id="assettField" name="qty" label="Quantity" value="{!v.newAsset.Quantity}" />
    
    <lightning:input aura:id="assetField" type="Price" name="price" label="Price"
 value="{!v.newAsset.Price}"/>
    <lightning:input aura:id="assetField" type="Description" name="description" label="Description"
 value="{!v.newAsset.Description}" />
    
    <lightning:button label="Cancel" onclick="{!c.handleCancel}"
 class="slds-m-top_medium" />
    <lightning:button label="Save Asset" onclick="{!c.handleSaveAsset}"
 variant="brand" class="slds-m-top_medium"/>
	
</aura:component>

Below is the Component’s Controller – AccountAssetActionController.js

<!--AccountAssetActionController.js-->
({
	doInit : function(component, event, helper) {
        // Prepare the action to load account record
        var action = component.get("c.getAccount");
        action.setParams({"accountId": component.get("v.recordId")});
        // Configure response handler
        action.setCallback(this, function(response) {
        var state = response.getState();
        if(state === "SUCCESS") {
        component.set("v.account", response.getReturnValue());
        } else {
        console.log('Problem getting account, response state: ' + state);
        }
        });
        $A.enqueueAction(action);
   },
        handleSaveAsset: function(component, event, helper) {
        if(helper.validateAssetForm(component)) {
            // Prepare the action to create the new contact
        var assetAction = component.get("c.saveAssetWithAccount");
        assetAction.setParams({
        "asset": component.get("v.newAsset"),
        "accountId": component.get("v.recordId")
        });
        // Configure the response handler for the action
        assetAction.setCallback(this, function(response) {
        var state = response.getState();
        if(state === "SUCCESS") {
        // Prepare a toast UI message
        var resultsToast = $A.get("e.force:showToast");
        resultsToast.setParams({
        "title": "Asset Saved",
        "message": "The new Asset was created."
        });
        // Update the UI: close panel, show toast, refresh account page
        $A.get("e.force:closeQuickAction").fire();
        resultsToast.fire();
        $A.get("e.force:refreshView").fire();
        }
        else if (state === "ERROR") {
        console.log('Problem saving asset, response state: ' + state);
        }
        else {
        console.log('Unknown problem, response state: ' + state);
        }
        });
        // Send the request to create the new contact
        $A.enqueueAction(assetAction);
        }
  },
    handleCancel: function(component, event, helper) {
        $A.get("e.force:closeQuickAction").fire();
  }
})

For the Helper.js – AccountAssetActionHelper.js-

({
	validateAssetForm: function(component) {
        var validAsset = true;
        
        var assetValidFields = component.find('assetField').reduce(function (validFields,
        inputComp) {
        inputComp.showHelpMessageIfInvalid();
        return validFields && inputComp.get('v.validity').valid;
        }, true);
        if (assetValidFields) {
       
        var account = component.get("v.account");
            if($A.util.isEmpty(account)) {
            validAsset = false;
            console.log("Quick action context doesn't have a valid account.");
            }
        return(validAsset);
        }
   }
})

Below is the Apex class used as the server-side controller for the above component.

public class AccountAssetAction {
      
     @AuraEnabled
    public static Account getAccount(Id accountId) {
    // Perform isAccessible() checks here
    return [SELECT Name, BillingCity, BillingState FROM Account WHERE Id =
    :accountId];
    }
    @AuraEnabled
    public static Asset saveAssetWithAccount(Asset asset, Id accountId) {    
        asset.AccountId = accountId;
        upsert asset;
   		 return asset;
    }
}

The first method of the Apex code above retrieves an account based on the record ID while the second associates a new asset record with an account, and then saves it to the database.

Check how I created the action using the codes in the post in Create Asset Using Custom Action on Account Record Page

Reference

Lightning Aura Components Developer Guide