So I have the following request with which I am trying to do the following:
Look for a collection with the name 'questionnaires'
Look at a specific document with id, given by the parameter of the function
Take the reference of a collection 'questions' within this document
public async getQuestionnaire(
questionnaireId: string,
): Promise<FirebaseFirestore.CollectionReference<DocumentData>> {
const questionsCollection = await getFirestore().collection(
'questionnaires/{questionnaireId}/questions/',
);
return questionsCollection;
}
I tried both by obtaining the reference in one line or seperating it the following way:
public async getQuestionnaire(
questionnaireId: string,
): Promise<FirebaseFirestore.CollectionReference<DocumentData>> {
const questionnairesCollection =
getFirestore().collection('questionnaires');
const desiredQuestionnaire = questionnairesCollection.doc(questionnaireId);
const questions = desiredQuestionnaire.collection('questions');
return questions;
}
The method is called from the following get request handler:
#Get('/firebase/questionnaire/:questionnaireId')
#OpenAPI({ summary: 'Return a questionnaire' })
async getQuestionnaire(#Param('questionnaireId') questionnaireId: string) {
const questionsRef = await this.firebaseService.getQuestionnaire(
questionnaireId,
);
return { data: questionsRef };
}
The interesting thing is that if I print out the reference, I get exactly what I want. However when I try to return it, I get the following error:
[GET] /firebase/questionnaire/3iz5K3hsVvaFBwkyzd57 >> StatusCode:: 500,
Message:: Value for argument "documentPath" is not a valid resource path. Path must be a non-empty string.
My app is trying to make an API call and display the data from it in a modal. It isn't working because I'm storing the response from the API call as an array at the moment, meaning I can't access the sub-elements of the response.
My question, then: is there some way to either:
Store an object using State so that I can conveniently reference parts of that object?
OR
Parse an array as a JSON so I can take the data from the response and process it as a JSON when needed?
I realise this is kind of a weird question, so any answer that would achieve the same result would also be great.
Here's my code:
const DrinkPopup = (props) => {
let [drinkDetails,setDrinkDetails] = useState([])
let selectedDrinkId = props.drink
const getDrinkAsync = async (selectedDrinkId) => {
try {
let response = await fetch('https://www.thecocktaildb.com/api/json/v1/1/lookup.php?i='+selectedDrinkId);
let data = await response.json();
setDrinkDetails(data.drinks)
return true;
} catch (error) {
console.error(error);
}
}
useEffect (() => {
getDrinkAsync(selectedDrinkId)
console.log(selectedDrinkId)
console.log(drinkDetails)
},[]);
return(
<Modal isVisible={props.modalVisible}
onBackdropPress={()=>{props.setModalVisible(false)}} //allows closing modal by tapping outside it or back button
onBackButtonPress={()=>{props.setModalVisible(false)}}
animationIn={"slideInUp"}>
<View style={styles.infocard}>
<View style={styles.titleBox}>
<Text style={styles.header}>{drinkDetails.idDrink}</Text>
</View>
</View>
</Modal>
)
}
A really easy way to convert your array to an object is to use Object.assign like so:
Object.assign({}, data.drinks)
It would return an object with numbered keys and you can store that to state.
I'm using React-Slick to render <Report /> components in a carousel. I would like to sync each <Report />'s reportId with query params.
For example, a user would be able to see a specific report by going to myapp.com/reports?id=1 and it would take them to that specific "slide".
The problem I'm having is that the report data is being loaded before the slides are initialized. I can't find any good examples of react-slick's onInit or onReInit.
Instead of using onInit or onReInit, I just utilized the initialSlide setting and used componentDidUpdate().
componentDidUpdate = (prevProps, prevState) => {
const queryParams = qs.parse(this.props.location.search)
if (prevProps.reports !== this.props.reports) {
const sortedReports = this.sortReportsByDate(this.props.reports)
this.setSlideIndex(sortedReports.findIndex(i => i.id === parseInt(queryParams.reportId, 10)))
this.setQueryParams({
reportId: this.sortReportsByDate(this.props.reports)[this.state.slideIndex].id
})
}
if (prevState.slideIndex !== this.state.slideIndex) {
this.setQueryParams({
reportId: this.sortReportsByDate(this.props.reports)[this.state.slideIndex].id
})
}
}
And the settings:
const settings = {
...
initialSlide: reportsSortedByDate.findIndex(i => i.id === parseInt(queryParams.reportId, 10))
...
}
I hope someone finds this useful!
Hi Im trying to delete attached item from list items first and then upload new attach file in sharepoint using pnp js (in vuejs)!
i trace the code and delete part is runnging but i dont konw why attached file doesnt delete!!!
this is my code for deleting attached item
public async DeleteItemsAttachment(itemId: number): Promise<any> {
let item = pnp.sp.web.lists.getById('{128EF67A-FDSF-4F42-8E8F-D3FC9523273E}').items.getById(itemId)
return await item.attachmentFiles.deleteMultiple()
}
public async AddanAttachment(itemId: number, fileName: string, arrayBuffer: File): Promise<any> {
let item = pnp.sp.web.lists.getById('{128EF6AA-FD8F-4F42-8E8F-D3FC9523273E}').items.getById(itemId)
return await item.attachmentFiles.add(fileName, arrayBuffer)
}
uploadFile(){
if (this.itemId != null && this.myfiles) {
if (this.HasUploadFile) {
this.spService.DeleteItemsAttachment(this.itemId).then(response => {
this.AddAnAttachmentToRecord()
}).catch(e => {
this.message = ` exception : ${e}`
})
}
else {
this.AddAnAttachmentToRecord()
}
}
How can i solve my problem?
where is wrong area of my code?
According to attachmentfiles.ts deleteMultiple function expects the array of attachment file names, so attachments could be deleted by explicitly providing file names:
item.attachmentFiles.deleteMultiple("{attachment-file-name-1}","{attachment-file-name-2}")
or (more dynamic way) by reading attachment names and specifying it in deleteMultiple function:
let item = sp.web.lists.getByTitle(listTitle).items.getById(itemId);
//1. get all attachments
let attachments = await item.attachmentFiles.get();
let attachmentNames = attachments.map(a => a.FileName);
//2. delete all attachmanents
await item.attachmentFiles.deleteMultiple(...attachmentNames);
I am using Axios with NodeJs and trying to pass path parameters in axios.get() method. For example, if URL is url = '/fetch/{date}', I want to replace {date} with the actual date while calling axios.get(url).
I went through the source code on Github and StackOverflow, but couldn't find any method.
Is it possible to keep URLs with parameters as a placeholder and replace them while actually calling the get method of Axios?
Axios doesn't have this feature and it looks like the team don't want to add it.
With credit to previous responders for inspiration, to me this seems like the solution closest to what you (and me) are looking for:
1 - Where you want to store all your URLs and their parameters, define them as functions which use a template string to return the composed URL:
export var fetchDateUrl = (date) => `/fetch/${date}`;
If you need any type-specific formatting of the value being concatenated into the URL, this function is a good place to do it.
2 - Where you want to make the request, call the function with the correct parameters:
import { fetchDateUrl } from 'my-urls';
axios.get(fetchDateUrl(someDateVariable))...;
Another variation, if you really like the idea of naming the parameters at the call site, you can define the URL function to destructure an object like this:
var fetchDateUrl = ({date}) => `/fetch/${date}`;
which you'd then use like this:
axios.get(fetchDateUrl({date: someDateVariable}));
Use template strings
url = `/fetch/${date}`
Or just tag it on
url = '/fetch/'+ date
I think using axios interceptors is better to do this :
//create your instance
const instanceAxios = axios.create({
baseUrl: 'http://localhost:3001'
]);
instanceAxios.interceptors.request.use(config => {
if (!config.url) {
return config;
}
const currentUrl = new URL(config.url, config.baseURL);
// parse pathName to implement variables
Object.entries(config.urlParams || {}).forEach(([
k,
v,
]) => {
currentUrl.pathname = currentUrl.pathname.replace(`:${k}`, encodeURIComponent(v));
});
const authPart = currentUrl.username && currentUrl.password ? `${currentUrl.username}:${currentUrl.password}` : '';
return {
...config,
baseURL: `${currentUrl.protocol}//${authPart}${currentUrl.host}`,
url: currentUrl.pathname,
};
});
// use like :
instanceAxios.get('/issues/:uuid', {
urlParams : {
uuid: '123456789'
}
})
For typescript users, you will need to add this, in one of your .d.ts
declare module 'axios' {
interface AxiosRequestConfig {
urlParams?: Record<string, string>;
}
}
( this is a POC, not really tested, doesn't hesitate if you see something wrong )
You can use template strings ie:
let sellerId = 317737
function getSellerAnalyticsTotals() {
return axios.get(`http://localhost:8000/api/v1/seller/${sellerId}/analytics`);
}
Given some API /fetch/${date} you likely want to wrap your axios call in a function.
const fetchData = (date) => axios.get(`/fetch/${date}`);
fetchData(dateObject.toFormat('yyyy-mm-dd'))
.then(result => { ... });
This requires the calling code to format date correctly however. You can avoid this by using a DateTime library that handles date string parsing and do the format enforcement in the function.
const fetchData = (date) => axios.get(`/fetch/${date.toFormat('yyyy-mm-dd')}`);
fetchData(dateObject)
.then(result => { ... });
you can do like this:
getProduct = (id) => axios.get(`product/${id}`);
I always do it like this:
const res = await axios.get('https://localhost:3000/get', { params: { myParam: 123 } });
I find this to be much clearer than template strings.
More explanation here