I want to update the BuiltList in the state if some condition is met. Here is my reducer
TravelDeductionsStateBuilder _travelDeductionBreakfastToggled(
TravelDeductionsStateBuilder state,
TravelDeductionBreakfastToggledAction action) =>
state
..days = state.days.build().rebuild((d) {
if (d[action.key].deductions.contains(TravelDeductionType.BREAKFAST)) {
d[action.key]
.deductions
.rebuild((p0) => p0.remove(TravelDeductionType.BREAKFAST));
} else {
d[action.key]
.deductions
.rebuild((p0) => p0.add(TravelDeductionType.BREAKFAST));
}
}).toBuilder();
I need to add/remove ENUM entry into deductions but it seems that this update is ignored and I am not able to update this list accordingly. Any tips of what may be wrong?
If anyone wonders this is the solution
TravelDeductionsStateBuilder _travelDeductionBreakfastToggled(
TravelDeductionsStateBuilder state,
TravelDeductionBreakfastToggledAction action) =>
state
..days = state.days.build().rebuild((d) {
if (d[action.index]
.deductions
.contains(TravelDeductionType.BREAKFAST)) {
d[action.index] = d[action.index].rebuild(
(b) => b.deductions.remove(TravelDeductionType.BREAKFAST));
} else {
d[action.index] = d[action.index]
.rebuild((b) => b.deductions.add(TravelDeductionType.BREAKFAST));
}
}).toBuilder();
You can find the explanation here https://github.com/google/built_collection.dart/issues/259#issuecomment-1122390601
Related
I'm fetching data from an API that contains details of some person with their job. That could happen that one person has more than one job.
In this case, I don't want to add this person to a list but I want to append the current job title to the existing one.
Here is the snippet of the code:
if (workers.any((item) => item.id == person.id)) {
//here I want to append the job title.
} else {
workers.add(coWorker);
}
Maybe you can do something like this:
if (workers.any((item) => item.id == person.id)) {
final worker = workers.firstWhere((item) => item.id == person.id);
worker.jobTitle += 'appended text to jobTitle if that is a string';
} else {
workers.add(coWorker);
}
I Have 2 Audit tables one is Audit_ProfileFan and second is Audit_StatusChanges
The first table AuditProfileFan should audit every time update or insert has been made to ProfileFan Table.
The second Audit_StatusChanges should only audit when an update of a certain column FanStatusId is made.
Audit.Core.Configuration.Setup() .UseEntityFramework(ef => ef.AuditTypeExplicitMapper(m => m
.Map<FanActivity, Audit_FanActivity>((fanActivity, auditFanActivity) =>
{
auditFanActivity.ProfileFanId = fanActivity.ProfileFanId;
auditFanActivity.ActivityId = auditFanActivity.ActivityId;
})
.Map<DeliveryActions, Audit_DeliveryActions>((deliveryAction, auditDeliveryAction) =>
{
auditDeliveryAction.ProfileFanId = deliveryAction.FanId;
auditDeliveryAction.DeliveryActionId = deliveryAction.DeliveryActionId;
})
.Map<Fan, Audit_Fan>()
.Map<ProfileFan, Audit_StatusChanges>((profileFan, auditStatusChanges) =>
{
auditStatusChanges.ProfileFanId = profileFan.Id;
//auditStatusChanges.OriginalValue = profileFan.FanStatusId;
//auditStatusChanges.NewValue = profileFan.FanStatusId;
})
.Map<ProfileFan, Audit_ProfileFan>((profileFan, auditProfileFan) =>
{
auditProfileFan.ProfileFanId = profileFan.Id;
auditProfileFan.FanId = profileFan.FanId;
auditProfileFan.EmailResponseStatusId = profileFan.EmailResponseStatusId;
auditProfileFan.FanStatusId = profileFan.FanStatusId;
})
.Map<TagFan, Audit_TagFan>((tagFan, auditTagFan) =>
{
auditTagFan.ProfileFanId = tagFan.ProfileFanId;
auditTagFan.TagId = tagFan.TagId;
})
.AuditEntityAction<IAuditLog>((evt, entry, auditEntity) =>
{
if(entry.Table=="ProfileFan" && entry.Action=="Update")
{
//auditEntity.OriginalValue = profileFan.FanStatusId;
//auditEntity.NewValue = profileFan.FanStatusId;
}
auditEntity.AuditDate = DateTime.Now;
auditEntity.AuditUser = evt.Environment.UserName;
auditEntity.Action = entry.Action; // Insert, Update, Delete
auditEntity.AuditUsername = HttpContext.Current.User.Identity.Name;
})
)
);
But every time an update is made it audits only one table in this case Audit_ProfileFan.
Is my requirement possible or should I do some kind of workaround?
This is not possible with the current version of the EntityFramework data provider, since you can only map from the known entity type and nothing else.
But I've found a way to allow that kind of use cases with minimal impact, by adding a new Map<T> overload that lets you specify the final audit type as a function of the EventEntry, so you would be able to map the same input data type to multiple output audit types, depending on the modified entry.
So for example you could map ProfileFan to different tables depending on the SQL operation (insert/update), with something like this:
Audit.Core.Configuration.Setup()
.UseEntityFramework(ef => ef.AuditTypeExplicitMapper(m => m
.Map<ProfileFan>(
mapper: entry => entry.Action == "Insert" ? typeof(Audit_ProfileFan) : typeof(Audit_StatusChanges),
entityAction: (ev, entry, entity) =>
{
if (entity is Audit_ProfileFan pf)
{
// action for profile fan
// pf.xxxx = ...;
}
else if (entity is Audit_StatusChanges ss)
{
// action for status changes
// ss.xxxx = ...;
}
})
.Map<TagFan, Audit_TagFan>(/*...*/)
.AuditEntityAction<IAuditLog>((evt, entry, auditEntity) =>
{
// common action...
})));
This will be released soon, here is the commit with the changes.
UPDATE
This is included on Audit.EntityFramework library starting on version 14.6.2
Is there a better way to validate a row in ag-grid than with valueSetter?
I can achieve the validation with that but I am not sure, if there is a better way.
https://www.ag-grid.com/javascript-grid-value-setters/#properties-for-setters-and-parsers
I want to validate two fields in the row. DateFrom and DateUntil (they are not allow to be null and DateFrom must be lower than DateUntil).
There are two ways of possible validation handling:
First: via ValueSetter function
and
Second: via custom cellEditor component
I suggest that it would be better to split the logic between custom components, but as you said you need to validate two cell-values between themselves.
On this case from UI perspective you could try to combine them inside one cell and it would be easily to work with values via one component only.
You could override the valueSetter and call the grid api transaction update instead.
Here is pseudo-code that shows how you could implement this.
valueSetter: params => {
validate(params.newValue, onSuccess, onFail);
return false;
};
validate = (newvalue, success, fail) => {
if (isValid(newValue)) {
success();
} else {
fail();
}
};
onSuccess = () => {
// do transaction update to update the cell with the new value
};
onFail = () => {
// update some meta data property that highlights the cell signalling that the value has failed to validate
};
This way you can also do asynchronous validation.
Here is a real example of an async value setter that has success, failure, and while validating handlers that do transaction updates when validation is done.
const asyncValidator = (
newValue,
validateFn,
onWhileValidating,
onSuccess,
_onFail
) => {
onWhileValidating();
setTimeout(function() {
if (validateFn(newValue)) {
onSuccess();
} else {
_onFail();
}
}, 1000);
};
const _onWhileValidating = params => () => {
let data = params.data;
let field = params.colDef.field;
data[field] = {
...data[field],
isValidating: true
};
params.api.applyTransaction({ update: [data] });
};
const _onSuccess = params => () => {
let data = params.data;
let field = params.colDef.field;
data[field] = {
...data[field],
isValidating: false,
lastValidation: true,
value: params.newValue
};
params.api.applyTransaction({ update: [data] });
};
const _onFail = params => () => {
let data = params.data;
let field = params.colDef.field;
data[field] = {
...data[field],
isValidating: false,
lastValidation: params.newValue
};
params.api.applyTransaction({ update: [data] });
};
const asyncValidateValueSetter = validateFn => params => {
asyncValidator(
params.newValue,
validateFn,
_onWhileValidating(params),
_onSuccess(params),
_onFail(params)
);
return false;
};
Here is a code runner example showing this in action: https://stackblitz.com/edit/async-validation-ag-grid-final
Have a look at this two snippets, these come from our internal knowledge base (accessible to customers)
When editing a value in column 'A (Required)', you will see that it does not allow you to leave it empty. If you leave it empty and return the edit, it will be cancelled.
//Force Cell to require a value when finished editing
https://plnkr.co/edit/GFgb4v7P8YCW1PxJwGTx?p=preview
In this example, we are using a Custom Cell Editor that will also validate the values against a 6 character length rule. While editing, if the value is modified outside of 6 characters, it will appear in red, and when you stop editing the row, the value would be reset, so it only accepts a complete edit if the value is valid.
//Inline Validation while editing a cell
https://plnkr.co/edit/dAAU8yLMnR8dm4vNEa9T?p=preview
I'd like to have a search input, that display the result on keypress.
At the moment, this is what I have :
mylist: Observable<MyData[]>;
term = new FormControl();
ngOnInit() {
this.mylist = this.term.valueChanges
.debounceTime(400)
.distinctUntilChanged()
.switchMap(term => this.searchData(term));
}
searchData(valueToSearch:string){
if(valueToSearch == ''){
this.channels = MyData.find();
}
return MyData.find({'title':new RegExp(valueToSearch)});
}
It works quite well, but I have trouble to initialize "mylist", and I think my method isn't performant at all.
Basically, I want when my component is initialize, that:
this.mylist = MyData.find();
And on keypress, I want my search to be done on this.mylist, to avoid doing too much request.
Is it possible ?
I hope I'm clear.
Thanks by advance guys.
You must subscribe to the mapped data. Modify to the below code
this.term.valueChanges
.debounceTime(400)
.distinctUntilChanged()
.switchMap(term => this.searchData(term))
.subscribe((result) => {
this.mylist = result
});;
#Julia is correct , modify your searchData() function as below
searchData(valueToSearch:string):Observable<any> {
if(valueToSearch == ''){
this.channels = MyData.find();
}
return <Observable<any>>MyData.find({'title':new RegExp(valueToSearch)});
}
As I understand, ordered assertions in FakeItEasy 2 are done like this (from the docs):
// Assert
A.CallTo(() => unitOfWorkFactory.BeginWork()).MustHaveHappened()
.Then(A.CallTo(() => usefulCollaborator.JustDoIt()).MustHaveHappened())
.Then(A.CallTo(() => unitOfWork.Dispose()).MustHaveHappened());
Now, suppose I have a collection and for each item in this collection I want to assert that a call was made to a faked object. What is the best approach to assert the calls were made in the correct order?
I came up with this, but don't really like it:
IOrderableCallAssertion ioca = null;
foreach (var item in items.OrderBy(i => i.Id)
{
var itemUnderTest = item;
if (ioca == null)
{
ioca = A.CallTo(() => fakeObject.Handle(itemUnderTest, otherArgument)).MustHaveHappened(Repeated.Exactly.Once);
}
else
{
ioca = ioca.Then(A.CallTo(() => fakeObject.Handle(itemUnderTest, otherArgument)).MustHaveHappened(Repeated.Exactly.Once));
}
}
That looks about right to me. Of course, you could inline itemUnderTest and pull MustHaveHappened outside of the two if branches.
And you could always hide this in a convenience method.
An alternative: use Invokes to capture the fakes as the calls come in and later compare them against a list.