How do I edit embed and add new fields? - discord

There is an Embed in which fields will be added and information will change, depending on the reactions.
How do I make changes to embed and add and remove fields?
If I try to edit via edit, it changes the entire message and inserts only the modified message
const exampleEmbed = new Discord.MessageEmbed()
.setColor('RANDOM')
.setTitle(`${day.format("DD.MM.YY, в (HH:mm)")}`)
.setAuthor('Destiny 2', 'https://www.neira.app/img/Destiny2.png', 'https://www.bungie.net/')
.setDescription(`**Заметка от лидера:** ${c.join(' ')}`)
.setThumbnail(image_raid)
.addField('Информация', `- Лидер группы: **#1** ${message.author}\n- Нажмите на реакцию`)
.setFooter(`ID: ${message.id}`)
let jsonStr = messageReaction.message.embeds[0];
var obj = JSON.parse(JSON.stringify(jsonStr));
obj['fields'].push(
{
"value": "4",
"name":"pending",
"inline":false
});
jsonStr = JSON.stringify(obj);
messageReaction.message.edit("#here", { embed: jsonStr });

You should simply use, in your add reaction code:
const newEmbed = messageReaction.message.embeds[0];
newEmbed.addField('pending', 4, false);
messageReaction.message.edit("#here", {
embed: oldEmbed
});

What you're looking for is the #addField() method. To add new fields externally, simply do <embedName>.addField()
Here is an example of how embeds work:
// at the top of your file
const Discord = require('discord.js');
// inside a command, event listener, etc.
const exampleEmbed = new Discord.MessageEmbed()
.setColor('#0099ff')
.setTitle('Some title')
.setURL('https://discord.js.org/')
.setAuthor('Some name', 'https://i.imgur.com/wSTFkRM.png', 'https://discord.js.org')
.setDescription('Some description here')
.setThumbnail('https://i.imgur.com/wSTFkRM.png')
.addFields(
{ name: 'Regular field title', value: 'Some value here' },
{ name: '\u200B', value: '\u200B' },
{ name: 'Inline field title', value: 'Some value here', inline: true },
{ name: 'Inline field title', value: 'Some value here', inline: true },
)
.addField('Inline field title', 'Some value here', true)
.setImage('https://i.imgur.com/wSTFkRM.png')
.setTimestamp()
.setFooter('Some footer text here', 'https://i.imgur.com/wSTFkRM.png');
channel.send(exampleEmbed);

Related

discord js 14 slashcommand embed [duplicate]

This question already has an answer here:
why register slash commands with options doesn't work (discord.js)
(1 answer)
Closed last month.
const { SlashCommandBuilder, CommandInteraction, EmbedBuilder, Client } = require('discord.js');
module.exports = {
data:new SlashCommandBuilder()
.setName("createEmbed")
.setDescription("Create new test Embed!"),
/**
*
* #param {CommandInteraction} interaction
* #param {Client} client
*/
async excute (interaction, client) {
const exampleEmbed = new EmbedBuilder()
.setColor(0x0099FF)
.setTitle('Some title')
.setAuthor({ name: 'Some name' })
.setDescription('Some description here')
.addFields(
{ name: 'Regular field title', value: 'Some value here' },
{ name: '\u200B', value: '\u200B' },
{ name: 'Inline field title', value: 'Some value here', inline: true },
{ name: 'Inline field title', value: 'Some value here', inline: true },
)
.addFields({ name: 'Inline field title', value: 'Some value here', inline: true })
.setTimestamp()
.setFooter({ text: 'Some footer text here' });
await interaction.reply({
embeds: [exampleEmbed]
});
},
};
console
D:\감기여요\visual studio code\discord_bot\test_discord_bot\node_modules#sapphire\shapeshift\dist\index.js:76
throw this.error;
^
ExpectedConstraintError: Invalid string format
at Object.run (D:\감기여요\visual studio code\discord_bot\test_discord_bot\node_modules#sapphire\shapeshift\dist\index.js:1564:64) at D:\감기여요\visual studio code\discord_bot\test_discord_bot\node_modules#sapphire\shapeshift\dist\index.js:142:66
at Array.reduce ()
at StringValidator.parse (D:\감기여요\visual studio code\discord_bot\test_discord_bot\node_modules#sapphire\shapeshift\dist\index.js:142:29)
at Object.validateName (D:\감기여요\visual studio code\discord_bot\test_discord_bot\node_modules#discordjs\builders\dist\interactions\slashCommands\Assertions.cjs:11:17)
at MixedClass.setName (D:\감기여요\visual studio code\discord_bot\test_discord_bot\node_modules#discordjs\builders\dist\interactions\slashCommands\mixins\NameAndDescription.cjs:9:16)
at Object. (D:\감기여요\visual studio code\discord_bot\test_discord_bot\commands\createembed.js:5:10)
at Module._compile (node:internal/modules/cjs/loader:1105:14)
at Object.Module.extensions..js (node:internal/modules/cjs/loader:1159:10)
at Module.load (node:internal/modules/cjs/loader:981:32) {
constraint: 's.string.regex',
given: 'createEmbed',
expected: 'expected /^[\p{Ll}\p{Lm}\p{Lo}\p{N}\p{sc=Devanagari}\p{sc=Thai}-]+$/u.test(expected) to be true'
}
I've tried countless methods, but all of them have the same result.
Any good ideas?
I am new to programming
Command names cannot contain upper case letters. createEmbed has a capital E which is in violation of the constraint as described by the regex. Rename createEmbed to something else like create-embed.

Discord JS MessageSelectMenu

I would like to add an option to an existing MessageSelectMenu that I created like this:
button = new MessageActionRow().addComponents(
new MessageSelectMenu()
.setCustomId('selects')
.setPlaceholder('Test')
.addOptions([
{
label: 'test1',
value: '1',
},
])
)
For example, I would like to add this option:
{
label: 'test2',
value: '2',
},
I can't do it.
Can you help me?
Thank you in advance for your answers.
To make Discord Select Menus you can follow:
const button = new MessageActionRow()
.addComponents(
new MessageSelectMenu()
.setCustomId('selects')
.setPlaceholder('Test')
.addOptions([
{
label: 'test1',
description: 'This is a description',
value: '1',
},
// if you want to add another option in THIS menu you can continue below:
label: 'You can select me too',
description: 'This is also a description',
value: 'second_option',
},
]),
);
For receiving Select Menus attach an eventlistner to client you can use Interaction.isSelectMenu()
client.on('interactionCreate', async interaction => {
if (!interaction.isSelectMenu()) return;
if(interaction.CustomId === 'selects'){
await interaction.update('selected')
}
});

Refresh Datatable in for:each loop: Lightning Web Components

I am having trouble refreshing a Datatable in my Lightning Web Component after updating a record. I am calling an onclick action on a button within the row, and imperatively calling an Apex method to update that record. I then call the refreshApex() to update the data being fed into the Datatable.
However, after the refreshApex(), the tables within the for:each are not being refreshed with new data.
The records are properly modified and reflect the changes properly when refreshing the entire page.
Note: The Task object is not supported in LWC, and I cannot use the updateRecord() method to update these records.
HTML:
<template>
<template if:true="{taskCompWrapperList}">
<!--<lightning-layout multiple-rows="false" pull-to-boundary="small">-->
<template for:each="{taskCompWrapperList}" for:item="taskTemplate">
<lightning-layout-item
key="{taskTemplate.taskSectionOrder}"
size="3"
class="slds-p-around_x-small"
>
<!-- Start bear tile -->
<lightning-card title="{taskTemplate.taskSectionTitle}">
<div class="slds-m-around_medium">
<template if:true="{taskTemplate.taskList}">
<lightning-datatable
key-field="Id"
data="{taskTemplate.taskList}"
onrowaction="{handleRowAction}"
columns="{columns}"
onsave="{handleSave}"
draft-values="{draftValues}"
>
</lightning-datatable>
</template>
<template if:true="{contact.error}">
<!-- handle Apex error -->
</template>
</div>
</lightning-card>
<!-- End bear tile -->
</lightning-layout-item>
</template>
<!--</lightning-layout>-->
</template>
</template>
Javascript:
import { LightningElement, api, wire ,track} from 'lwc';
import getTaskCompWrappers from '#salesforce/apex/ENT_Task_Utility.getTaskComponentWrapper';
import updateTask from '#salesforce/apex/ENT_Task_Utility.updateTask';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { updateRecord } from 'lightning/uiRecordApi';
import { refreshApex } from '#salesforce/apex';
const COLS = [
{
type: 'button',
label: 'Complete',
typeAttributes:
{
//iconName: 'action:preview',
label: 'Complete',
name: 'Complete',
title: 'Complete',
value: 'Complete',
variant: 'brand',
alternativeText: 'Complete'
}
},
{
type: 'button-icon',
label: 'Start',
typeAttributes:
{
iconName: 'action:approval',
//label: 'Complete',
name: 'Start',
title: 'Start',
value: 'Start',
variant: 'success',
alternativeText: 'Start',
}
},
{
type: "button",
typeAttributes:
{
label: 'View',
name: 'View',
title: 'View',
disabled: false,
value: 'view',
iconPosition: 'left'
}
},
{
type: "button",
typeAttributes:
{
label: 'Edit',
name: 'Edit',
title: 'Edit',
disabled: false,
value: 'edit',
iconPosition: 'left'
}
},
//{ label: 'Complete', fieldName: 'Task_Complete__c', editable: true },
{ label: 'Status', fieldName: 'Status', type: 'picklist', editable: true },
{ label: 'Completed', fieldName: 'Completed', type: 'boolean', editable: true },
{ label: 'Owner', fieldName: 'OwnerId', editable: true },
{ label: 'Subject', fieldName: 'Subject' },
{ label: 'Due Date', fieldName: 'ActivityDate', type: 'date' }
];
export default class ENT_Task_Utility_LWC extends LightningElement {
#api objApiName;
#api recordId;
#track testMessage = 'Test Failed :c';
#track error;
#track columns = COLS;
#track draftValues = [];
taskCompWrapperList;
#track error;
//#wire(getTasks, {recordId: '$recordId'}) taskList;`
#wire(getTaskCompWrappers, {recordId: '$recordId', objApiName: '$objApiName'})
taskCompWrapperListWire({ error, data }) {
if (data) {
this.taskCompWrapperList = data;
this.error = undefined;
} else if (error) {
this.error = error;
this.taskCompWrapperList = undefined;
}
}
updateTaskValues (taskId, taskStatus) {
// eslint-disable-next-line no-console
console.log('updateTaskValues hit');
for(var counter = 0; counter < this.taskCompWrapperList.length; counter++) {
// eslint-disable-next-line no-console
console.log('taskWrapper: ' + this.taskCompWrapperList[counter]);
for(var counter2 = 0; counter2 < this.taskCompWrapperList[counter].taskList.length; counter2++) {
// eslint-disable-next-line no-console
console.log('task: ' + this.taskCompWrapperList[counter].taskList[counter2]);
if(this.taskCompWrapperList[counter].taskList[counter2].Id == taskId)
{
this.dispatchEvent(
new ShowToastEvent({
title: 'Task Id Found!',
message: this.taskCompWrapperList[counter].taskList[counter2].Id,
variant: 'success'
})
);
this.taskCompWrapperList[counter].taskList[counter2].Status = taskStatus;
}
}
}
}
handleRowAction(event) {
//TODO
}
}
Apex methods:
#AuraEnabled(cacheable=true)
global static List<Task> getTasks(String recordId)
{
return [SELECT Id, Subject, OwnerId FROM Task WHERE WhatId = :recordId];
}
#AuraEnabled(cacheable=true)
global static List<ENT_Task_Comp_Wrapper> getTaskComponentWrapper(String recordId, String objApiName)
{
List<Task_Template__c> taskTemplateList = [SELECT Id, Task_Component_Section_Order__c, Task_Component_Section_Title__c, (SELECT Id FROM Task_Template_Items__r)
FROM Task_Template__c
WHERE Active__c = true AND sObject__c = :objApiName ORDER BY Task_Component_Section_Order__c ASC];
List<Task> taskList = [SELECT Id, Task_Template_Item__c, OwnerId, Owner.Name, Subject, Description, Status, ActivityDate, Task_Complete__c FROM TasK WHERE WhatId = :recordId];
List<ENT_Task_Comp_Wrapper> taskCompWrapperList = new List<ENT_Task_Comp_Wrapper>();
for(Task_Template__c taskTemplate : taskTemplateList)
{
ENT_Task_Comp_Wrapper taskCompWrapper = new ENT_Task_Comp_Wrapper();
taskCompWrapper.taskSectionTitle = taskTemplate.Task_Component_Section_Title__c;
taskCompWrapper.taskSectionOrder = (Integer)taskTemplate.Task_Component_Section_Order__c;
taskCompWrapper.taskList = new List<Task>();
for(Task currentTask : taskList)
{
for(Task_Template_Item__c taskTemplateItem : taskTemplate.Task_Template_Items__r)
{
if(taskTemplateItem.Id == currentTask.Task_Template_Item__c)
{
taskCompWrapper.taskList.add(currentTask);
}
}
}
taskCompWrapperList.add(taskCompWrapper);
}
System.debug(taskCompWrapperList);
return taskCompWrapperList;
}
#AuraEnabled
global static void updateTask(String taskId, String newStatus)
{
System.debug(taskId);
Task taskToUpdate = new Task(Id = taskId, Status = newStatus);
update taskToUpdate;
//update taskToUpdate;
}
#AuraEnabled
global static void updateTask(String taskId, String newStatus)
{
System.debug(taskId);
Task taskToUpdate = new Task(Id = taskId, Status = newStatus);
update taskToUpdate;
//update taskToUpdate;
}
In your JS code you have imported refreshApex
by using this line import { refreshApex } from '#salesforce/apex';
but you didn't assigned to any wire method. Hence data is not refreshed
Please refer this documentation.
To refresh a wired method, pass the argument the wired method receives (which is the wired value) to refreshApex(). In this sample code, the wired method is taskCompWrapperListWire. Hold on to the value provisioned by the wire service and pass it to refreshApex().
#wire(getTaskCompWrappers, {recordId: '$recordId', objApiName: '$objApiName'})
taskCompWrapperListWire({ error, data }) {
if (data) {
this.taskCompWrapperList = data;
this.error = undefined;
} else if (error) {
this.error = error;
this.taskCompWrapperList = undefined;
}
}
And then use refreshApex() as below:
refreshApex(this.taskCompWrapperListWire);
Update you code as below
updateTaskValues({
taskId: this.taskId,
taskStatus: this. taskStatus
})
.then(() => {
// your code logic
refreshApex(this.taskCompWrapperListWire);
})
.catch((error) => {
this.message = 'Error received: code' + error.errorCode + ', ' +
'message ' + error.body.message;
});
you probably need to wait for next release to have a correct way to handle such situation.
You are getting record through uiRecordApi and updating through Apex if I'm correct.
Then you would need to use getRecordNotifyChange() available in Winter 21 release.
Apart from the answer provided by Sudarshan, you should also define taskCompWrapperList as a reactive property to make it rerender when the property is updated.
#track taskCompWrapperList = [];

Dynamically setting the options for an ActionSheet in Ionic 2

I am making a GET request to get back some JSON containing an array of options. Within each element I have an id, style and a name.
Based on the response I would like to dynamically set the options of my ActionSheet in my Ionic 2 app.
This ActionSheet works fine. My challenge is setting the options dynamically based on the API response.
let actionSheet = this.actionSheetCtrl.create({
title: 'Change the tag of this visitor',
buttons: [
{
text: 'Destructive red',
cssClass: 'label-red',
handler: () => {
myFunction(1);
}
},
{
text: 'Archive blue',
cssClass: 'label-dark-blue',
handler: () => {
myFunction(2);
}
},
{
text: 'Cancel',
role: 'cancel',
handler: () => {
console.log('Cancel clicked');
}
}
]
});
I would like the keep the cancel option but show my own options above -- i.e. remove the destructive and archive options.
In PHP I would achieve this with this pseudo code ..
$options = array();
$options['title'] = 'Change the tag of this visitor';
$buttons = array();
foreach($api_response as $a) {
array_push($buttons, array('text' => $a['name'], 'cssClass' => $a['style']) );
}
$options['buttons'] = $buttons;
let actionSheet = this.actionSheetCtrl.create(json_encode($options));
And then my final question is how I can specify the appropriate value of id from the elements that I am looping through as the parameter for the myFunction() call ... e.g set the value of XX to be 1 when id=1, 20 when id=20, etc
e.g.
text: 'Name goes here',
cssClass: 'label-red',
handler: () => {
myFunction(XX);
}
I seem to have found a better way to solve this problem. I am using the addButton method ..
let actionSheet = this.actionSheetCtrl.create({
title: 'Change the tag of this visitor'
});
this.http.get('http://api.domain.com/tags', {headers:headers}).map(res => res.json()).subscribe(data => {
for (var i = 0; i < data.res.length; i++) {
actionSheet.addButton({text: data.res[i].name, cssClass: data.res[i].style });
}
});
actionSheet.addButton({text: 'Cancel', 'role': 'cancel' });
actionSheet.present();

How to customize the UriCell's render of BackGrid

I have the following
name: "id", // The key of the model attribute
label: "User Id", // The name to display in the header
editable: false, // By default every cell in a column is editable, but *ID* shouldn't be
cell: Backgrid.UriCell.extend({
orderSeparator: ''})
}, {
Using the Backgrid.UriCell has
href: formattedValue,
title: formattedValue**,
Is there any way that define href has "session" + formatedValue ? In other words, how to customize the UriCell so I can define href different from title?
Try this:
var UriCell = Backgrid.UriCell.extend({
render: function () {
this.$el.empty();
var rawValue = this.model.get(this.column.get("name"));
var formattedValue = this.formatter.fromRaw(rawValue, this.model);
var href = _.isFunction(this.column.get("href")) ? this.column.get('href')(rawValue, formattedValue, this.model) : this.column.get('href');
this.$el.append($("<a>", {
tabIndex: -1,
href: href || rawValue,
title: this.title || formattedValue,
target: this.target
}).text(formattedValue));
this.delegateEvents();
return this;
}
});
Then, you can write this:
name: "id",
label: "User Id",
editable: false,
cell: UriCell,
href: function(rawValue, formattedValue, model){
return "session" + formattedValue;
}

Resources