Can't create a LookUpField - javascript

I am creating a new list and trying to add a LookUp field on the list.
I retrieve the list I want to look up against:
let list = sp.web.lists.getByTitle("Trucks");
list.get().then(list => {
this._ensureMyList("MySPListTest", list)
});
I then create the new list and the new field:
private _ensureMyList(listName: string, truckList): void {
sp.web.lists.ensure(listName)
.then((ler: ListEnsureResult) => {
if (ler.created) {
console.log("list was created");
ler.list.fields.add("LookupTest", "SP.FieldLookup", {
Group: "~Example",
FieldTypeKind: 7,
Filterable: true,
Hidden: false,
EnforceUniqueValues: true,
})
.then((result) => {
console.log("result: ", result);
});
}
});
}
I get the error:
Uncaught (in promise) Error: Error making HttpClient request in queryable: [500] ::> {"responseBody":{"odata.error":{"code":"-2146232832, Microsoft.SharePoint.SPException","message":{"lang":"en-US","value":"Please use addfield to add a lookup field instead."}}},"responseHeaders":{}}
I got the Field name and TypeKind from:
https://msdn.microsoft.com/en-us/library/office/dn600182.aspx#bk_FieldLookup
I also tried using the addLookup method:
ler.list.fields.addLookup("LookupTest", truckList.Id, "Truck")
.then((result) => {
console.log("result: ", result);
});
With error:
Uncaught (in promise) Error: Error making HttpClient request in queryable: [400] ::> {"responseBody":{"odata.error":{"code":"-1, Microsoft.SharePoint.Client.InvalidClientQueryException","message":{"lang":"en-US","value":"The parameter __metadata does not exist in method AddField."}}},"responseHeaders":{}}

You could consider the following options to add lookup field:
1) via Fields.addLookup method:
let list = await sp.web.lists.getByTitle(listTitle); //get list resource
let lookupList = await sp.web.lists.getByTitle(lookupListTitle).select("Id").get(); //select Lookup List Id
let field = await list.fields.addLookup(lookupFieldName, lookupList.Id ,"Title"); // add lookup field to list
2) via Fields.createFieldAsXml method:
let list = await sp.web.lists.getByTitle(listTitle); //get target list resource
let lookupList = await sp.web.lists.getByTitle("Categories").select("Id").get(); //determine lookup list id
let fieldXml = `<Field Name="Category" Type="Lookup" DisplayName="Category" List="{${lookupList.Id}}" ShowField="Title"/>`; //construct lookup field schema
let field = await list.fields.createFieldAsXml(fieldXml); //add field to list
References
PnPjs Add Fields
Update
Regarding the error which occurs while invoking Fields.addLookup method:
the parameter __metadata does not exist in method AddField.
it seems there is a bug with in the latest version (v1.2.1) for Fields.addLookup method. The point is it generates invalid payload, something like this:
{
"__metadata":{
"type":"SP.FieldCreationInformation"
},
"parameters": {
"FieldTypeKind":7,
"LookupFieldName":"Title",
"LookupListId":"{list-id}",
"Title":"Cat"
}
}
parameters should be the root tag in payload for http://<site url>/_api/web/lists(guid'<list id>')/fields('<field id>')/addfield endpoint (source)
According to the history this bug has been introduced with one of the later commit, anyway it's better to report an issue.

Related

HubspotClient - Update contact by email id is not working

In NodeJS, I'm using "#hubspot/api-client": "^7.1.2".
Created hubspot client using accessToken as follows
const hubSpotClient = new hubspot.Client({ accessToken });
When I try to update the contact using email it's throwing error
Request:
const idProperty = 'email';
const response = await hubSpotClient(store).crm.contacts.basicApi.update(email, idProperty, contact);
Response:
ERROR {
"statusCode": 404,
"body": {
"status": "error",
"message": "Object not found. objectId are usually numeric.",
"correlationId": "71e911d3...",
"context": {
"id": [
"testemail#..."
]
},
"category": "OBJECT_NOT_FOUND"
}
Create contact is working fine with this client but updating by email is not working.
Anything out of place or syntax error in passing the idProperty?
The problem is in your implementation, because it seems like you are not using properly the Hubspot API.
If you check the function signature of the basicApi.update
public async update(contactId: string, simplePublicObjectInput: SimplePublicObjectInput, idProperty?: string, _options?: Configuration): Promise<RequestContext> {
Basically, you need to pass down a contactId, and then a simplePublicObjectInput that is basically an object that represents your update.
Your code should look like this:
import { Client } from "#hubspot/api-client";
const hubspotClient = new Client({ accessToken: YOUR_ACCESS_TOKEN });
const contactID = 1234;
const response = await hubspotClient.crm.contacts.basicApi.update(contactID, {
properties: { email: 'my-new-email#gmail.com' },
})
Keep in mind that Hubspot always tries to follow their same guidelines as their endpoints. If your check the endpoint specification you will see the following:
Think about the Hubspot node client as just an abstraction of some http client, but at the end does exactly the same as the endpoints described in their implementations.
For that reason, in your implementation, Hubspot is returning an appropriated error, since you are not giving the contactId in the first argument, Hubspot is telling you: "Object not found. objectId are usually numeric." Because indeed a Contact ID is numeric and you are using the value of an email --string-- instead.
If you want to "update by email"
I think that there is no direct way to do it, you might need to do a previous search of the contact by email.
You could use the searchApi.
And after getting the id just run the update.
const searchResponse = await hubspotClient.crm.contacts.searchApi.doSearch({
filterGroups: [
{
filters: [
{
value: 'email-to-search#gmail.com',
propertyName: 'email',
operator: 'EQ',
},
],
},
],
sorts: [],
properties: [],
limit: 1,
after: 0,
});
// Off course you need to improve a lot the error handling here and so on.
// This is just an example
const [contactID] = searchResponse.results;
const contactUpdateResponse = await hubspotClient.crm.contacts.basicApi.update(contactID, {
properties: { email: 'my-new-email#gmail.com' },
})
I hope this helps you!
You CAN use email as the idProperty for the hubspot/api-client get contact function, but it only works if you fill in all the other query fields before idProperty, even if they are undefined.
Here is my example of a getContactByEmail as a Google Cloud Function in Node, using the api-client, and it works great!
exports.getContactByEmail = functions.https.onCall(async (data, context) => {
const email = data.email;
const contactId = email;
const properties = ["firstname", "lastname", "company"];
const propertiesWithHistory = undefined;
const associations = undefined;
const archived = false;
const idProperty = "email";
try {
const apiResponse = await hubspotClient.crm.contacts.basicApi.getById(
contactId,
properties,
propertiesWithHistory,
associations,
archived,
idProperty
);
console.log(JSON.stringify(apiResponse.body, null, 2));
return apiResponse.properties;
} catch (error) {
error.message === "HTTP request failed"
? console.error(JSON.stringify(error.response, null, 2))
: console.error(error);
return error;
}
});

Axios Post inside loop with changing variable REACT

I have an array of labels for form inputs named changing_variable, which are dependent on what a user selects from a drop down menu, so these are unknown.
I need to be able to let the property of the Axios.post method, equal to the variable in order to input the correct data into my database.
Any examples I see online have properties like:
name: this.name
age: this.age
However this cannot work for me since I cannot hard code the values since they change depending on the user input, and also there is over a hundred for each user input.
If anyone can help me pass this changing variable to my backend. Thanks
My current code :
var i;
var changing_variable;
for(i=1; i<arr.length; i++)
{
changing_variable = inputValues[i].text
Axios.post(URL, changing_variable)
.then(res => {
console.log(res);
console.log(res.data);
console.log(changing_variable)
})
}
};
EDIT
Node.js code
app.post('/create', (req,res) => {
const test_variable= req.body.changing_variable;
db.query("INSERT INTO iptable (test_variable) VALUES(?)",
[test_variable], (err,result) =>{
if(err){
console.log(err)
}else {
res.send("Values Inserted")
}
}
)
});
Terminal error message
code: 'ER_BAD_NULL_ERROR',
errno: 1048,
sqlMessage: "Column 'test_variable' cannot be null",
sqlState: '23000',
index: 0,
sql: 'INSERT INTO iptable (test_variable) VALUES(NULL)'
The solution is Using application/x-www-form-urlencoded, URLSearchParams
By default, axios serializes JavaScript objects to JSON. To send data in the application/x-www-form-urlencoded format instead, you can use the URLSearchParams API.
const params = new URLSearchParams({ foo: 'bar' });
params.append('extraparam', 'value');
axios.post('/foo', params);
REF https://github.com/axios/axios#urlsearchparams

I get undefined when i try to add an Object from an api to my mongodb atlas db NODE JS

I get a list of pokemons from a third party API. I want to add specific ones to a favorites list when I click the add button. but whenever I try to render the list of favourite pokemon i just get objects saying undefined.
Any help would be appreciated.
//Here i try to add the fetched object to my rest api//
function createPokemonCard(data) {
const pokeContainer = document.getElementById("poke-container");
const pokemonEl = document.createElement('div');
pokemonEl.classList.add('pokemon');
const pokeInnerHtml = `
<div class="img-container">
<img src="${data.sprites.front_default}">
</div>
<div class="pokeCard">
<h1 id="id">${data.id}</h1>
<h3 id="name">${data.name}</h3>
<h4 id="type">${data.types.map(type => type.type.name).join(", ")}</h4>
<button onclick="addFavourite()">Add</button>
</div>
`;
pokemonEl.innerHTML = pokeInnerHtml;
pokeContainer.appendChild(pokemonEl);
}
// i am trying to get the value//
async function addFavourite() {
let name = document.getElementById('name').value ;
let type = document.getElementById('type').value ;
let data = {
"name": name,
"type": type
}
await fetch('https://web2-course-project-api-somrad.herokuapp.com/api/pokemons', {
method: "POST",
mode: 'cors',
headers: {
'Content-type': 'application/json; charset=utf-8'
},
body: JSON.stringify(data)
});
}
// my back end post request//
pokemonRouter.route('/pokemons')
//POST YOUR FAVOURITE POKEMON
.post((req, res)=>{
const collection = db.collection("pokedex");
collection.insertOne(req.body).then(
() => {
res.status(200).json({
message: 'Added!'
});
}
).catch(
(error) => {
res.status(400).json({
error: error
});
});
})
this is my collection, the first three entries is added manually
The list probably prints "undefined" since some of the objects provided by the database don't have a name.
[
{"_id":"610d3316bf52a4e260126877","name":"Pikachu","type":"Electric"},
{"_id":"610e689defe3ad8654648ec3","name":"Charmander","type":"Fire"},
{"_id":"610e68acefe3ad8654648ec4","name":"Bulbasaur","type":"Grass"},
{"_id":"6118df7554b38705559eaacd"},
{"_id":"6118f0e493b20fefb0fd1689"},
{"_id":"6118f1e7128dd43ee68f8140"},
{"_id":"6118f2e8128dd43ee68f8141","name":"test","type":"grass"},
{"_id":"6118f57a128dd43ee68f8142"},
{"_id":"6118f5ca128dd43ee68f8143"},
{"_id":"6118f6a6128dd43ee68f8144"},
{"_id":"6118f6da128dd43ee68f8145"},
{"_id":"6118f6fd128dd43ee68f8146"},
{"_id":"6118f86f128dd43ee68f8147"},
{"_id":"6118f8e4128dd43ee68f8148"},
{"_id":"6118f924128dd43ee68f8149"},
{"_id":"6118fb34128dd43ee68f814a"}
]
This already includes my other suggestions.
I recommend that you filter out the invalid ones before rendering the rest.
// your list with the pokemon before you create the html elements
// this simply removes all pokemon from the list that don't have a name or type
const yourList = [];
const yourFilteredList = yourList.filter(item => {
if(item.name === undefined) return false;
if(item.type === undefined) return false;
return true;
})
Please also note that in mongoDB the Primary Key of the database is _id not id
<h1 id="id">${data._id}</h1>
This could also be an issue, since the type field of the API you provided is a string not a list as indicated. This may result in an Uncaught TypeError: something.join is not a function
<h4 id="type">${data.types.map(type => type.type.name).join(", ")}</h4>

discord.js Editting Slash Command Interaction Messages

So I'm using discord.js with this code here:
client.api.interactions(interaction.id, interaction.token).callback.post({
data: {
type: 4,
data: {
content: "Getting Data..."
}
}
})
I would like to be able to edit this message afterwards, but everything I have seen requireds a message id, and I seem to be unable to get the message id off of this code.
You can edit an interaction response with this patch request (See: Followup Messages):
PATCH /webhooks/<application_id>/<interaction_token>/messages/#original
Basic example using the axios library:
axios.patch(`https://discord.com/api/v8/webhooks/${appId}/${interaction.token}/messages/#original`, { content: 'New content' });
The answer to this request will also contain the message-id.
Here is an example function that will edit the original message either as plain text or an embed object and returns the discord message object for further usage (e.g. add reply emojis etc.):
const editInteraction = async (client, interaction, response) => {
// Set the data as embed if reponse is an embed object else as content
const data = typeof response === 'object' ? { embeds: [ response ] } : { content: response };
// Get the channel object by channel id:
const channel = await client.channels.resolve(interaction.channel_id);
// Edit the original interaction response:
return axios
.patch(`https://discord.com/api/v8/webhooks/${appId}/${interaction.token}/messages/#original`, data)
.then((answer) => {
// Return the message object:
return channel.messages.fetch(answer.data.id)
})
};
Also instead of sending an initial message like "getting data..." you also can send an empty response of type 5. This is the build-in method and displays a little loading animation too :) See here (One advantage is that this way no "edited" appears.)
client.api.interactions(interaction.id, interaction.token).callback.post({
data: {
type: 5,
},
})

How to associate a child element with a parent using SQLAlchemy Full stack dev udacity course

In the course you are supposed to make a form that creates 'todos' and then have a parent list as well. Everything worked fine until we were instructed to add a foreign key 'list_id' to the child so that it associates with the parent list. After that when I attempt to create a todo I get the integrity error saying that the list_id is null and goes against the constraint since it is set to nullable=false. How do I get the todos(child) table to associate to the parent(list) table so that is automatically matches the list_id to the parent's id? They are already set up to have a relationship but it is still not associating them. Below is the back end code to model the tables.
'''
'''
Back end to create the todo
'''
#app.route('/todos/create', methods=['POST'])
def create_todo():
error = False
body = {}
try:
description = request.get_json()['description']
todo = Todo(description=description)
db.session.add(todo)
db.session.commit()
body['description'] = todo.description
except:
db.session.rollback()
print(sys.exc_info())
finally:
db.session.close()
print("i am in todo")
if error:
abort(400)
else:
return jsonify(body)
'''
This is the front side javascript for the create form
'''
document.getElementById('form').onsubmit = function(e) {
e.preventDefault();
const desc = descInput.value;
//descInput.value = '';
console.log(desc);
fetch('/todos/create', {
method: 'POST',
body: JSON.stringify({
'description': desc,
}),
headers: {
'Content-Type': 'application/json',
}
})
.then(response => response.json())
.then(jsonResponse => {
console.log('response', jsonResponse);
li = document.createElement('li');
li.innerText = desc;
document.getElementById('todos').appendChild(li);
document.getElementById('error').className = 'hidden';
})
.catch(function() {
document.getElementById('error').className = '';
})
}
'''
In your server code you have to explicitly set todo list to your newly created todo object before you save it (e.g. todo = Todo(description=description, list_id=some_todolist.id)), otherwise the nullable=False constraint will trigger. How you get the needed todolist object there depends on how you provide the "this todo should under this list" idea, e.g. provide the list id through request params, if the frontend knows about that.

Categories