I am stuck while trying to trigger a CanJs event with newVal.I have a change event like below:
"{ApplicationShell.AppState.processState.modelExecution} change": function (model, ev, attr, how, newVal, oldVal) {
if (newVal === "Something"){
}
}
So here i have to trigger this event. I can trigger this event using below code:
can.trigger(ApplicationShell.AppState.processState.modelExecution,"change")
But i couldn't pass a value to newVal of the changed event. I tried to pass like below:
can.trigger(Sentrana.ApplicationShell.AppState.processState.modelExecution,"change","abcd");
But this "abcd" is passed to the attr of the event method not in the newVal parameter.
So is there any way to pass value to the newVal using can trigger?
Yeah we can send value to the newVal using can.trigger().
can.trigger(ApplicationShell.AppState.processState.modelExecution,"change",["a","b", "c", "d"])
Now the values will go the trigger event like below:
"a" -> attr "b" -> how "c" -> newVal "d" -> oldVal
Related
I have a
export const selectIDs = creteSelector(
selectorFeature,
(feature: Feature) => {
return feature?.metadata?.ids || []
}
}
in the component I have
this.store.select(selectIDs).subscribe((ids) => dosomething(ids))
When the system is up feature is undefined so [] is passed into the callback. Then feature then changes to a normal value but .metadata not available so select returns [] which is same as last result so the dosomething() call back is not supposed to be called. But it actually get called again in my code with []
My question is if both time selector returns a [], shouldn't the calllback (those calls in subscribe)be called once?
Or generally I mean if I do this:
this.store.select(featueSelector).subscribe((feature) => console.log(feature)
suppose global state changes 10 times, but feature stays same so featureSelector returns same feature, will the console.log() be called 10 times? I imagine the console.log() will only be called when what feature selectore returns is different from last time?
Thanks
=================== updated =============
it turns out this.store.select() returns a observable, so when the obserable calls the next(), console.log() will be called.
Ngrx selector memorize means it directly returns same value if input is same.
The selector is fired again, and a new array instance is returned.
Because [] === [] is falsy, the new instance is passed to the subscribe method.
As a workaround, you can:
filter our empty array: this.store.select().pipe(filter(arr => arr.length > 0 )).subscribe())
use the distinct operator: this.store.select().pipe(distinct(insertCheckHere)).subscribe())
I think you can also create a variable const empty = [] and return empty in the selector instead of []
I want to be able to run a lambda and get at its argument values (the values of a and b below).
I can achieve this by explicitly having the lambda return a binding, and then getting the values out of this binding:
fun = lambda { |a, b = Time.now| binding }
fun_binding = fun.call(123)
puts "A is #{fun_binding.local_variable_get(:a)} and B is #{fun_binding.local_variable_get(:b)}"
# Outputs e.g.: A is 123 and B is 2022-04-29 20:14:07 +0200
Is it possible to get these values without running any code inside the lambda body? I.e. could I do
fun = lambda { |a, b = Time.now| }
fun.call(123)
and still get the a and b values somehow from outside the lambda?
(To provide context – I'm asking because I've experimented with this as a shortcut syntax for instantiating objects with ivars/readers automatically assigned. At this stage I'm more curious about what's possible than what is advisable – so I invite any solutions, advisable or not…)
I'm not sure how advisable this is, but you can use the TracePoint class with the :b_call event to grab the lambda's binding:
fun = lambda { |a, b = Time.now| }
fun_binding = nil
TracePoint.trace(:b_call) do |tp|
fun_binding = tp.binding
tp.disable
end
fun.call(123)
puts "A is #{fun_binding.local_variable_get(:a)} and B is #{fun_binding.local_variable_get(:b)}"
This is not a perfect solution and will fail if one of the argument default values enters a block on it's own (since the default values are evaluated before the :b_call event is fired for the lambda), but that could be fixed with some additional filtering inside the TracePoint handler.
I am spying on method emit of EventEmitter in Angular
spyOn(answerComponent.answerEmitter, 'emit');
I want to check that emit was called with an argument A but I don't want to check exact match with A. I want to check that emit was called with values A.a, A.b and ignore value of A.c.
Is it possible to do so?
Use jasmine.objectContaining.
const emit = spyOn(answerComponent.answerEmitter, 'emit');
expect(emit).toHaveBeenCalledWith(jasmine.objectContaining({ a: <value>, b: <value>));
Two ways come to my mind:
One by using the native toHaveBeenCalledWith
expect(answerComponent.answerEmitter, 'emit').toHaveBeenCalledWith(A.a);
expect(answerComponent.answerEmitter, 'emit').toHaveBeenCalledWith(A.b);
// you can think of all the callers being tracked as an array and you can assert with
// toHaveBeenCalledWith to check the array of all of the calls and see the arguments
expect(anserComponent.anserEmitter, 'emit').not.toHaveBeenCalledWith(A.c); // maybe you're looking for this as well
You can also spy on the emit and call a fake function:
spyOn(answerComponent.answerEmitter, 'emit').and.callFake((arg: any) => {
// every time emit is called, this fake function is called
if (arg !== A.a || arg !== A.b) {
throw 'Wrong argument passed!!'; // you can refine this call fake
} // but the point is that you can have a handle on the argument passed and assert it
});
I have a simple struct Foo:
struct Foo {
let bar: String
}
Now I create an unbounded ReplaySubject of Foos:
let subject = ReplaySubject<Foo>.createUnbounded()
How can I now understand whether the (unterminated) stream has a Foo whose bar was equal to abc? (This could be the 1st, 3rd, or 20th element.)
First, this is kind of a crazy request. You should not be thinking about "what was" when working with Rx. Rather you should be thinking about what is always the case. You should be thinking about invariants...
That said, the operator below will emit the indexes for you. Since the subject is able to constantly emit events, the operator is designed to work in real time. It can be used like this:
let indexes = subject.indexOfElementSatisfying { $0.bar == "abc" }
Here it is:
extension ObservableConvertibleType {
/**
Emits the index of all the values in the stream that satisfy the predicate.
- parameter pred: The predicate that determines whether the value satisfies the condition
- returns: An observable sequence of indexes to those elements.
*/
func indexOfElementSatisfying(_ pred: #escaping (E) throws -> Bool) -> Observable<Int> {
return asObservable()
.enumerated()
.filter { try pred($0.element) }
.map { $0.index }
}
}
How do I convert an Observable of type Int to a Variable of type Int?
Here is what I have tried so far:
let obs: Observable<Int> = Observable.of(4)
let variable: Variable<Int> = obs
.flatMap { num in
return Variable<Int>(num)
}
Using flatMap feels like the most logical way of doing the conversion, however, I get a compiler error which essentially says that it does not like the flatMap returning anything that is not an observable. Any ideas?
EDIT:
Just to give some context as to why I need to convert the Observable into a Variable:
I need my viewModel to drive a UIPickerView inside a ViewController. Currently, I have two exposed properties in my ViewModel, items: Observable<[String]> (which is the datasource for the UIPickerView) and selectedIndex: Variable. The selectedIndex will drive the initial value of the UIPickerView but also keep track of any changes the user makes.
The reason I needed to convert from the Observable to Variable was that I needed to figure out which index of the UIPickerView should be selected initially:
items.map { days -> Int in
if let index = days.index(where: { str in
return str == selectedDay
}) {
return index
}
return 0
}
.flatMap { num in
return Variable<Int>(num)
}
I'm now wondering if I'm over complicating things, and if instead of the Variable in I should just have an Observable.
A few points here:
First, You should not use Variable as it's deprecated (gonna be entirely deprecated in Swift 5 probably). Look at BehaviorSubject and BehaviorRelay instead.
About your question, I'm not sure what is the use case for having a Variable equal to an Observable, so there are two different thoughts I have:
You can bind an Observable to a Variable/Subject/Relay (e.g. observable.bind(to: variable))
You can actually go the other way around an get an Observable from the Variable, which might make more sense. e.g. variable.asObservable()