I Have the following function in my code
private loadDrones() {
this.store$.dispatch(new UsedDronesStoreActions.GetUsedDronesRequest({organizations_id : environment.organizationId}));
this.store$.pipe(select(UsedDronesStoreSelectors.selectAll)).subscribe((drones) => {
drones.forEach((drone) => {
if (this.drones.has(drone.id)) { return; }
this.drones.set(drone.id, drone);
this.store$.dispatch(new UsedDronesStoreActions.OpenUsedDroneUpdatePositionChannelRequest({ droneId: drone.id, projectId : environment.projectId }));
this.store$.dispatch(new UsedDronesStoreActions.OpenUsedDroneUpdateStatusChannelRequest({ droneId: drone.id, projectId : environment.projectId }));
});
});
}
I would like to move this function into an INIT Action in my effect.
Using
#Effect()
init$ = this.actions$.pipe(
ofType(ROOT_EFFECTS_INIT),
map(action => ...)
);
My question is, , the actual function load a list, and then thank to the result of that list, dispatch a serie of actions for each element of the list.
Is it possible to make this inside a single effect ? Or do I have to split it up in 2 different actions ?
https://medium.com/#amcdnl/dispatching-multiple-actions-from-ngrx-effects-c1447ceb6b22
#Effect() save = this.update$.pipe(
map(action => action.payload),
switchMap(payload => this.myService.save(payload)),
switchMap(res => [
new Notification('save success'),
new SaveSuccess(res)
])
);
Related
I try to add a custom user field to the user by using WPGraphQL. Therefore I tried to recreate the example in the official WPGraphQL documentation https://docs.wpgraphql.com/extending/fields/#register-fields-to-the-schema :
add_action('graphql_init', function () {
$hobbies = [
'type' => ['list_of' => 'String'],
'description' => __('Custom field for user mutations', 'your-textdomain'),
'resolve' => function ($user) {
$hobbies = get_user_meta($user->userId, 'hobbies', true);
return !empty($hobbies) ? $hobbies : [];
},
];
register_graphql_field('User', 'hobbies', $hobbies);
register_graphql_field('CreateUserInput', 'hobbies', $hobbies);
register_graphql_field('UpdateUserInput', 'hobbies', $hobbies);
});
I already changed the type from \WPGraphQL\Types::list_of( \WPGraphQL\Types::string() ) to ['list_of' => 'String'].
If I now execute the updateUser mutation my hobbies don't get updated. What am I dowing wrong?
Mutation:
mutation MyMutation {
__typename
updateUser(input: {clientMutationId: "tempId", id: "dXNlcjox", hobbies: ["football", "gaming"]}) {
clientMutationId
user {
hobbies
}
}
}
Output:
{
"data": {
"__typename": "RootMutation",
"updateUser": {
"clientMutationId": "tempId",
"user": {
"hobbies": []
}
}
}
}
Thanks to xadm, the only thing I forgot was to really mutate the field. I was a bit confused by the documentation, my fault. (I really am new to WPGraphQL btw)
Here's what has to be added:
add_action('graphql_user_object_mutation_update_additional_data', 'graphql_register_user_mutation', 10, 5);
function graphql_register_user_mutation($user_id, $input, $mutation_name, $context, $info)
{
if (isset($input['hobbies'])) {
// Consider other sanitization if necessary and validation such as which
// user role/capability should be able to insert this value, etc.
update_user_meta($user_id, 'hobbies', $input['hobbies']);
}
}
I am new to ReactiveUI along with DynamicData
Declaration
ReadOnlyObservableCollection<Employee> itemSource;
public ReadOnlyObservableCollection<Employee> ItemSource
{
get => itemSource;
}
SourceList<Employee> Employees = new SourceList<Employee>();
Implementation
Employees
.Connect()
.Sort(SortExpressionComparer<Employee>.Ascending(emp => emp.ID))
.Bind(out itemSource)
.ObserveOn(RxApp.MainThreadScheduler)
.Do(_ =>
{
this.RaisePropertyChanged(nameof(ItemSource));
})
.DisposeMany()
.Subscribe()
.DisposeWith(disposable);
this.WhenAnyValue(x => x.itemSource)
.Do(_ =>
{
Debug.Print("Called");
});
But whenever I am calling
Employees.Add(new Employee
{
Name = "Hello" + DateTime.Now.ToShortDateString(),
ID = random.Next(1,1000)
});
I expect it to print "Called" in debug window as this.WhenAnyValue should be called, but apparently this is not the case.
Could you please help me to understand if I am doing any mistake?
Thanks Glen. I was able to fix it by using below code
this.WhenAnyValue(x => x.itemSource.Count)
.Do(_ =>
{
Debug.Print("Called");
});
I need to handle a situation where I have 3 endpoints to call and would like to get the data in the most convenient/efficient way. The first call can be handled independently and returns a single result. The second endpoint returns a collection but will need to initiate 0-* subsequent calls, where a given key is present.
Ideally would like to receive the collection (from the 2nd endpoint call) as a mutated/new collection that includes the result from the 3rd endpoint call.
I am currently using forkJoin(observableA$, observableB$) to handle the first 2 calls in parallel but I cannot work out how to include the sequential calls and have the data included in observableB$
//Customer observable
const customer$ = this._customerManagementService.getCustomer(
accountNumber
);
return forkJoin({
customer: customer$,
saleCycles: saleCyclesWithVehicle$
}).pipe(finalize(() => this._loaderFactoryService.hide()));
getSalesWithVehicle(accountNumber: string, dealerKey: string) {
return this._salesCycleService
.getCyclesForCustomer({
customerNumber: accountNumber,
dealerKey: dealerKey
})
.pipe(
concatMap((results: ISaleCycle[]) => {
return results.map(cycle => {
return this._purchaseVehicleService.getPurchaseVehicle(
cycle.vehicleKey
);
});
})
);
}
I expect the collection to include further data as a new property on the original collection
UPDATE
After a bit more thought maybe I should be using reduce somewhere in the solution. This way I can be in control of what's getting push into the array and it could be dynamic?
getSalesWithVehicle(accountNumber: string, dealerKey: string) {
return this._salesCycleService
.getCyclesForCustomer({
customerNumber: accountNumber,
dealerKey: dealerKey
})
.pipe(
switchMap((results: ISaleCycle[]) => {
return results.map(cycle => {
if (cycle.vehicleKey) {
return this._purchaseVehicleService
.getPurchaseVehicle(cycle.vehicleKey)
.pipe(
reduce((acc, vehicle) => {
return { cycle: cycle, vehicle: vehicle };
}, []),
toArray()
);
}
else {
///No extra data to be had
}
});
}),
concatAll()
);
}
I would use concatMap() to merge the responses of HTTP requests 2 and 3.
import { of } from 'rxjs';
import { map, concatMap } from 'rxjs/operators';
const pretendGetCustomer = of({accountNumber: 123, name:"John Doe"});
const pretendGetVehiculeHttpRequest = (customerNumber) => {
return of([{custNum: 123, vehicleId:"2"}, {custNum: 123, vehicleId:"1"}]);
}
const pretendGetCyclesHttpRequest = (cycleIds) => {
return of([{id:"1", name:"yellow bike", retailPrice:"$10"}, {id:"2", name:"red bike", retailPrice:"$20"}]);
}
const yourFunction = () => {
pretendGetCustomer.subscribe(customer => {
// Assuming you do other things here with cust, reason why we are subscribing to this separately
// isHappy(customer)
// Your second & third calls
pretendGetVehiculeHttpRequest(customer.accountNumber).pipe(
// Need to use concatMap() to subscribe to new stream
// Note: use mergeMap() if you don't need the 1st stream to be completed
// before calling the rest
concatMap(purchases => {
const cyclesIds = purchases.map(p => p.vehicleId);
// concatMap() requires an Observable in return
return pretendGetCyclesHttpRequest(cyclesIds).pipe(
// Use map() here because we just need to use the data,
// don't need to subscribe to another stream
map(cycles=>{
// Retrun whatever object you need in your subscription
return {
customerNumber: customer.accountNumber,
customerName: customer.name,
purchases: purchases.map(p => cycles.find(c => p.vehicleId === c.id))
}
})
);
})
).subscribe(resultof2and3 => {
// Do something with the new/mutated Object which is a result of
// your HTTP calls #2 and #3
console.log(resultof2and3);
});
});
}
yourFunction();
I made a stackblitz if you want to see the above run (see console): https://stackblitz.com/edit/rxjs-nqi7f1
This is the solution I eventually came up with. I've taken the advice from BoDeX and used concatMap(). In my mind it was clear that I wanted to use forkJoin and be able to reference the results by object key, I.e customer or saleCycles.
In the scenario where a vehicleKey was present I needed to return the results in a defined data structure, using map(). Likewise, if no vehicle was found then I just needed the outer observable.
const customer$ = this._customerManagementService.getCustomer(accountNumber);
const saleCyclesWithVehicle$ = this.getSalesWithVehicle(accountNumber,dealerKey);
getSalesWithVehicle(accountNumber: string, dealerKey: string) {
return this._salesCycleService
.getCyclesForCustomer({
customerNumber: accountNumber,
dealerKey: dealerKey
})
.pipe(
concatMap(cycles => {
return from(cycles).pipe(
concatMap((cycle: ISaleCycle) => {
if (cycle.vehicleKey) {
return this._purchaseVehicleService
.getPurchaseVehicle(cycle.vehicleKey)
.pipe(
map(vehicle => {
return { cycle: cycle, vehicle: vehicle };
})
);
} else {
return of({ cycle: cycle });
}
}),
toArray()
);
})
);
}
return forkJoin({
customer: customer$,
saleCycles: saleCyclesWithVehicle$
}).pipe(finalize(() => this._loaderFactoryService.hide()));
I have the following code in my View (cshtml):
#(Html.Kendo().DropDownListFor(model => model.CompetitionSubjectId)
.HtmlAttributes(new { style = "width:100%" })
.OptionLabel("choose")
.DataTextField("SubjectTitle")
.DataValueField("SubjectID")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetCascadeSubjects", "Participants")
.Data("filterSubjects");
})
.ServerFiltering(true);
})
.Enable(false)
.AutoBind(false)
.CascadeFrom("CompetitionBranchId")
What does the Data() do here?
I reckon it's related to the JS function filterSubjects:
function filterSubjects() {
return {
branches: $("#CompetitionBranchId").val()
};
}
Data() returns the value from whatever $("#CompetitionBranchId").val() is and passes it to the controller method GetCascadeSubjects.
My guess is that the controller action should look something like
public whatever GetCascadeSubjects(//Sometype branches)
The Read call is essentially doing the same as when you would pass a parameter to a controller action, such as:
read.Action("GetCascadeSubjects", "Participants", new {branches = #Model.Branches})
I'm trying to fix a problem from the code and don't understand why is not working.
Function:
export const monthlyKpiActions_disp = (threeMonthsBefore, currentDate) => {
console.log('kpppppppppppppppi')
return monthlyKpiActions.fetch({
filter: {
objectId,
interval: threeMonthsBefore + '/' + currentDate,
names: [
'ecostats_fuelusagetotal',
'ecostats_fuelrefmileage',
'ecostats_co2emission',
'tripstats_mileage',
'tripstats_drivingtime',
'optidrive_indicator_8'
].join(',')
},
forceUpdate: true,
resetState: false
})
}
redux
function mapDispatchToProps(dispatch) {
return {
monthlyKpiActions_func: (threeMonthsBefore, currentDate) => dispatch(monthlyKpiActions_disp(threeMonthsBefore, currentDate)),
}
}
calling the function
const currentDate = moment.utc().add(1, 'months').format(dateFormat)
const threeMonthsBefore = moment.utc().subtract(3, 'months').format(dateFormat)
{ () => this.props.monthlyKpiActions_func(threeMonthsBefore, currentDate) }
The problem is that never enters the function, any suggestions?
That's because you never call the action, this line
{ () => this.props.monthlyKpiActions_func(threeMonthsBefore, currentDate) }
Creates a block scope with an anonymous function which internally calls your action, but its never invoked (nor makes any sense in this context).
Just call the action:
this.props.monthlyKpiActions_func(threeMonthsBefore, currentDate)