How to use #pnp/sp to query a person column in an SP list to get the name - spfx

I have a web part that which needs to retrieve the Name property of a person column (a people picker) so I can populate state with it and subsequently populate a field. Here's the function that queries the item:
private _jeChange = (ev: React.FormEvent<HTMLDivElement>, option?: IDropdownOption, index?: number) => {
this.setState({
SelectedJE: option.text,
}, () => {
const selJE = this.state.SelectedJE;
if (selJE && selJE.length > 0) {
let _item = this.state.MyListItems.find((item) => {
return item.JobRef == selJE;
});
this.setState({
JEDeptContact: _item.DeptContactId,
}, () => {
sp.web.lists.getByTitle("MyList").items.getById(_item.Id).select("DeptContact", "Lookup/Name", "Lookup/ID").expand("Lookup").get().then((item: any[]) => {
console.log(item);
});
});
}
});
}
The _item.DeptContactId successfully populates the state with the Id of the user in the person column, but I want the Name not the Id, how would I resolve the Id to the Name? Do I need to use expand to get the Name? If so how?
I've read this but I don't know where to use the expand:
https://pnp.github.io/pnpjs/sp/items/

Found it:
if(_item.DeptContactId){
sp.web.getUserById(_item.DeptContactId).select("Title", "DeptContact/Title").expand("DeptContact").get().then(r => {
this.setState({
JEDeptContact: r.Title,
});
});

Related

Pusher Laravel Broadcast Leave Room Notification

I am going to post all my methods inside my app just to keep this clear for me to read. Here is the goal. When a user enters a room, a message is added "USER HAS ENTERED THE ROOM" - that works fine. Now, what I want to do is when a user LEAVES a room, I want it to say "USER HAS LEFT THE ROOM" - the notification works, but it is showing the wrong username (it shows the username of the person SEEING the message.
What is it I a missing or not grasping
methods: {
connect() {
if (this.currentRoom?.id) {
let vm = this;
this.getMessages();
Echo.join("chat." + this.currentRoom.id)
.here(users => {
this.sendUserActivityNotification(this.$page.props.user, true)
this.users = users
this.usersCount = users.length
})
.joining(user => {
this.users.push(user)
this.usersCount = this.usersCount+1
})
.leaving(user => {
this.sendUserActivityNotification(this.$page.props.user, false)
this.users = this.users.filter(({id}) => (id !== user.id))
this.usersCount = this.usersCount-1
})
.listen('NewChatMessage', (e) => {
vm.getMessages();
});
}
},
setRoom(room) {
this.currentRoom = room;
},
getMessages() {
axios.get('/chat/room/' + this.currentRoom.id + '/messages')
.then(response => {
this.messages = response.data;
})
.catch(error => {
console.log(error);
})
},
sendUserActivityNotification(user, joining) {
const message = `${user.name} has ${joining === true ? 'entered' : 'left'} the room.`
return axios.post(`/chat/room/${this.currentRoom.id}/notifications`, {message}).then(() => this.getMessages())
.catch(console.error)
},
leaveRoom({id}) {
this.$store.dispatch(RoomTypes.LEAVE_ROOM, id)
}
},
I haven't used Laravel Echo, but after reading your code I think on the leaving method call, you are passing current user instead of what you are receiving from the event when you call the sendUserActivityNotification method.
Your implementation looks like this:
...
.leaving(user => {
this.sendUserActivityNotification(this.$page.props.user, false)
this.users = this.users.filter(({id}) => (id !== user.id))
this.usersCount = this.usersCount-1
})
....
You are passing this.$page.props.user to this.sendUserActivityNotification method instead of passing user.
You must change that call to this.sendUserActivityNotification(user, false)

rxjs: subscribing to observable in map

My first observable returns an array of Persons. I want to update each person of that array with a list of clients from second observable. How do I do that? So far I have this:
const json: Person[] = [new Person('Alice'), new Person('Bob')];
const resultsObservable = new Observable<string[]>(subscriber => {
setTimeout(() => {
subscriber.next(['Client1', 'Client2', 'Client3']);
subscriber.complete();
}, 1000);
});
of(json).pipe(
switchMap( dataArray => {
return from(dataArray);
}),
map((x: Person) => {
resultsObservable.subscribe(r => {
x.clients = r;
});
return x;
}),
).subscribe(value => {
console.log(value);
});
}
Person:
export class Person{
name: string;
clients?: string[];
constructor(name: string) {
this.name = name;
}
}
But the problem is that return happens before the values are set, so at the end value of person.clients is undefined. How do I fix this? Or what is a better way to achieve what I'm trying to do?
Ok I think I found what I was looking for:
const result = persons.pipe(
mergeMap(p => resultsObservable.pipe(map(clients => {
p.clients = clients;
return p;
}))),
);
result.subscribe(p => console.log(p));

Vuejs function with multiple data

I have two data table in vue app.
Cash [code, description,cash]
Upload [bank, id]
For my update function, i need to take [bank, id] from upload and [cash] from cash. i don't know how, can someone help please ? Thank you. This is my code
This is my vuejs
var app = new Vue({
el: '#app',
data: {
cash: {
codeentry: '',
description: '',
cash: '',
},
upload: {
bank: '',
id: '',
},
},
methods: {
updateBank: function () {
axios.put('/updatebank', this.upload, this.cash)
.then(response => {
if (response.data.etat) {
this.upload.id = response.data.etat.id
this.upload.bank = response.data.etat.bank
this.cash.cash = response.data.etat.cash
}
})
.catch(error => {
console.log('errors: ', error)
})
},
}
});
My route :
Route::put('/updatebank', 'CoinController#updateBank');
Controller :
public function updateBank(Request $request)
{
$coin = Coin::findOrFail($request->id);
$coin->bank = ($request->bank - $request->cash);
$coin->save();
}
When i execute my function and see the report. Only this.upload is token in consideration.
If you mean to have the two data in one object, you can make a new object from the two objects
Es6 Example:
const {bank,id} = this.upload;
const {cash} = this.cash;
const my_data = {
bank, id, cash
}
Older Js example
var my_data = {
cash: this.cash.cash,
bank: this.upload.bank,
id: this.upload.id,
}
Otherwise, if you want to have both in the request as separate objects then wrap around them {}
var my_data = {
upload: this.upload,
cash: this.cash
}
Finally:
axios.put('/updatebank', my_data)
...
Update: It appears you don't want to merge those objects as different sub-object so your updateBank method would be like so:
updateBank: function () {
const my_data = {
cash: this.cash.cash,
bank: this.upload.bank,
id: this.upload.id,
};
axios.put('/updatebank', my_data)
.then(response => {
if (response.data.etat) {
this.upload.id = response.data.etat.id
this.upload.bank = response.data.etat.bank
this.cash.cash = response.data.etat.cash
}
})
.catch(error => {
console.log('errors: ', error)
});
}
Just a side observation, are you sure the this in the response references your Vue object?

How to get input field name that value has changed [ Angular 6 ]

I tried reactive form valueChanges but valueChanges method doesn't return input field name which has changed.
I thought code like this. but I think this is not smart way. Because I have to compare every each input field. so I need more smart way.
// get init view data from local storage
this.localstorageService.getPlaceDetail().subscribe(data => {
this.initPlaceDetail = data;
// watch changed value
this.editPlaceForm.valueChanges.subscribe(chengedVal => {
if (chengedVal['ja_name'] !== this.initPlaceDetail.languages.ja.name.text) {
this.changedJA = true;
}
if (chengedVal['ja_romaji'] !== this.initPlaceDetail.languages.ja.name.romaji) {
this.changedJA = true;
}
// ...... I have to check all input fields??
});
});
I'm adding form controls from an array and something like this worked for me. Just reference the item you need instead of expecting the valueChanges observable to pass it to you.
myFields.forEach(item => {
const field = new FormControl("");
field.setValue(item.value);
field.valueChanges.subscribe(v => {
console.log(item.name + " is now " + v);
});
});
This is my way to get changed control in form.
I shared for whom concerned.
Method to get list control changed values
private getChangedProperties(form): any[] {
let changedProperties = [];
Object.keys(form.controls).forEach((name) => {
let currentControl = form.controls[name];
if (currentControl.dirty)
changedProperties.push({ name: name, value: currentControl.value });
});
return changedProperties;
}
If you only want to get latest changed control you can use
var changedProps = this.getChangedProperties(this.ngForm.form);
var latestChanged = changedProps.reduce((acc, item) => {
if (this.changedProps.find(c => c.name == item.name && c.value == item.value) == undefined) {
acc.push(item);
}
return acc;
}, []);
Instead of listening to whole form changes you can listen to value changes event for each form control as shown in below code:
this.myForm.get('ja_name').valueChanges.subscribe(val => {
this.formattedMessage = `My name is ${val}.`;
});

Microsoft Bot Framework

I am trying to build A CONVERSATIONAL BOT. when I am trying to pass the response with next , its not getting reflected din the next functions .
bot.dialog('Barcode',
(session, args, next) => {
var intent = args.intent;
var id = builder.EntityRecognizer.findEntity(intent.entities, 'Report.Id');
if (id) {
next({ response: id.entity });
} else {
builder.Prompts.text(session, 'Please enter your id');
}
session.endDialog();
} ,
(session,results) => {
var id = results.response;
session.send(id.toString()); -- i want the value to be passed here
}
).triggerAction({
matches: 'Barcode'
})
If you want to implement a workflow in a dialog, you can set IDialogWaterfallStep|IDialogWaterfallStep[] in the second parameter in dialog() function.
In your code, you forget to cover [] outside the steps.
Try:
bot.dialog('Barcode',[
(session, args, next) => {
var intent = args.intent;
var id = builder.EntityRecognizer.findEntity(intent.entities, 'Report.Id');
if (id) {
next({ response: id.entity });
} else {
builder.Prompts.text(session, 'Please enter your id');
}
session.endDialog();
} ,
(session,results) => {
var id = results.response;
session.send(id.toString()); -- i want the value to be passed here
}]
).triggerAction({
matches: 'Barcode'
})

Resources