Remove Mapbox gl js render event listener - event-handling

I added a clustering service to my map, and i should remove this render event listener in some cases to avoid unnessesary map querys. Is there any usual way to do this?
export class MapClusterService {
clusterSource = 'search-results';
constructor(public mapService: MapService, private mapboxGlService: MapboxGlService, ) {this.updateMarkers = this.updateMarkers.bind(this);}
public async removeEventListeners() {
const map = await this.mapboxGlService.getMap();
map.off('render', this.updateMarkers); //this.updateMarkers() has error Argument of type 'Promise<void>' is not assignable to parameter of type '(ev: MapboxEvent<undefined> & EventData) => void'.
}
public async setUp() {
const map = await this.mapboxGlService.getMap();
console.log('setUP');
map.on('render', () => {
console.log('rendering');
this.updateMarkers();
});
}
updateMarkers is creating html divs for custom clusters.
Any idea would help, how to remove the event listener.

Related

Transform Freezed Events in BLoC

I'd like to know if there's a way to properly set BLoC Events using Freezed library. Problem appears when you want to add transformer into selected events.
Let's consider this scenario:
class CustomState {}
#freezed
class CustomEvent with _$CustomEvent {
const factory CustomEvent.regularEvent() = _RegularEvent;
const factory CustomEvent.eventWithTransformer() = _EventWithTransformer;
}
class CustomBloc extends Bloc<CustomEvent, CustomState> {
CustomBloc(CustomState initialState) : super(initialState) {
on<CustomEvent>((event, emitter) {
//handle Events
},
transformer: transformOnlyEventWithTransformer());
}
}
How can I add transform just for eventWithTransformer ?
on<CustomEvent.regularEvent>((event, emitter) {
//this won't work as ```CustomEvent.regularEvent``` is not a type
}
Also, you cannot have two on<> with same event in one bloc so below won't work either
on<CustomEvent>((event, emitter) {
event.whenOrNull(
regularEvent: () => // handle event
)
}
on<CustomEvent>((event, emitter) {
event.whenOrNull(
eventWithTransformer: () => // handle event
)
}, transformer: transformOnlyEventWithTransformer());
Let me know if there's any solution to this issue. If not, it'd nice to add this a feature request.
Had the similar issue problem,
I was originally doing
on<CustomEvent.RegularEvent>((event, emitter) {})
I fixed it by changing it to
on<RegularEvent>((event, emitter) {})
You'll have to make your events public for it to work, I would like it work with it but it's fine for my case.

How to send with 'params.put' in Dart or Flutter JsonObjectLite

In java it would be something like this ...
public Request compose(LoginDevice login) {
JSONObject params = new JSONObject();
try {
if (login.granType != null)
params.put("grant_type", login.granType);
if (login.clientId != null)
params.put("client_id", login.clientId);
} catch (JSONException e) {
e.printStackTrace();
}
return (Request)new BaseRequest("oauth/v2/token", params.toString(), new HashSet());
}
And in Dart and tried something similar but it doesn't work... the parameter 'put' does not exist in JsonObjectLite...
Request compose(LoginDevice login)
{
JsonObjectLite params = new JsonObjectLite();
try {
if (login.granType != null) {
params.put("grant_type", login.granType);
}
if (login.clientId != null) {
params.put("client_id", login.clientId);
}
} on JsonObjectLiteException catch (e) {
print(e);
}
return new BaseRequest("oauth/v2/token", params.toString(), new HashSet());
}
How could I do it? Thank you
The class JsonObjectLite doesn't contain the method put.
How you can understand dart doesn't is Java, in this cases your the class JsonObjectLite has a method called putIfAbsent, the implementation is the following
/// If [isImmutable] is false, or the key already exists,
/// then allow the edit.
/// Throw [JsonObjectLiteException] if we're not allowed to add a new
/// key
#override
void putIfAbsent(dynamic key, Function() ifAbsent) {
if (isImmutable == false || containsKey(key)) {
_objectData.putIfAbsent(key, ifAbsent);
} else {
throw const JsonObjectLiteException('JsonObject is not extendable');
}
}
look also the Source code
So an example of code should be the following
import 'package:json_object_lite/json_object_lite.dart';
class AuthorAnswer {
var _username;
var _status;
AuthorAnswer(this._username, this._status);
String get username => _username;
String get status => _status;
}
int main() {
var author = '#vincenzopalazzo';
var sentences = 'Follow me on Github';
var authorObject = AuthorAnswer(author, sentences);
try{
JsonObjectLite params = new JsonObjectLite();
params.isImmutable = false;
params.putIfAbsent("author", () => authorObject.username);
params.putIfAbsent("sencence", () => authorObject.status);
print(params.toString());
} on JsonObjectLiteException catch (err){
print('--------- ERROR ----------');
print(err);
}
return 0;
}
You should be set the params.isImmutable = false and after you can add your propriety, with your logic.
In my opinion, I don't see any motivation to use this library, dart have 2 types of the module to implement the serialization, and I think should better use it because on the web exist the documentation, like this dart json, flutter json
Inside the flutter app, there are also the line guides, for the small application you can use dart:convert:json also for the other you can use the json_serializable
I want to add also an example of dart:convert
/**
*
*/
import "dart:core";
import "dart:convert";
class ClassToJsonOne {
var _propOne;
var _propTwo;
ClassToJsonOne(this._propOne, this._propTwo);
Map<String, dynamic> toJSon() => {
'prop_one': _propOne,
'prop_two': _propTwo
};
ClassToJsonOne.fromJson(Map<String, dynamic> json):
_propOne = json['prop_one'],
_propTwo = json['prop_two'];
#override
String toString() => 'First Class: $_propOne, $_propTwo';
}
class ClassToJsonTwo{
var _propOne;
var _propTwo;
ClassToJsonTwo(this._propOne, this._propTwo);
Map<String, dynamic> toJSon() => {
'prop_one': _propOne,
'prop_two': _propTwo
};
ClassToJsonTwo.fromJson(Map<String, dynamic> json):
_propOne = json['prop_one'],
_propTwo = json['prop_two'];
#override
String toString() => 'Second Class: $_propOne, $_propTwo';
}
main(List<String> args) {
print('------- Declare Objecr -------\n');
var objectToJsonOne = ClassToJsonOne('I am the fist object', 'empty');
var objectToJsonTwo = ClassToJsonTwo('I contains the first object', 'empty');
String jsonStringObjOne = jsonEncode(objectToJsonOne.toJSon());
print('\n---------- Object one JSON format ---------\n');
print(jsonStringObjOne);
String jsonStringObjTwo = jsonEncode(objectToJsonTwo.toJSon());
print('\n---------- Object one JSON format ---------\n');
print(jsonStringObjTwo);
print('\n---------- DECODE JSON to OBJECT ---------\n');
var fromJsonObjectOne = jsonDecode(jsonStringObjOne);
print(fromJsonObjectOne.toString());
var fromJsonObjectTwo = jsonDecode(jsonStringObjTwo);
print(fromJsonObjectTwo.toString());
}
Inside the classes, you can see the following methods
Map<String, dynamic> toJSon() => {
'prop_one': _propOne,
'prop_two': _propTwo
};
ClassToJsonTwo.fromJson(Map<String, dynamic> json):
_propOne = json['prop_one'],
_propTwo = json['prop_two'];
The result of the method toJSon, you should be pass to the method of the library jsonEncode and when you go to deserialize you can use the library method jsonDecode(youtStringJSOn) and the result you can pass to the method of your class fromJson.
In addition, you can configure the library json_serializable.
In conclusion, I want to fix my comment
I think the json_serializable worked how GSON, I can make an example for you, on this day.
On flutter, documentation has reported this text
Is there a GSON/Jackson/Moshi equivalent in Flutter?
The simple answer is no.
Such a library would require using runtime reflection, which is disabled in Flutter. Runtime reflection interferes with tree shaking, which Dart has supported for quite a long time. With tree shaking, you can “shake off” unused code from your release builds. This optimizes the app’s size significantly.
Since reflection makes all code implicitly used by default, it makes tree shaking difficult. The tools cannot know what parts are unused at runtime, so the redundant code is hard to strip away. App sizes cannot be easily optimized when using reflection.
Although you cannot use runtime reflection with Flutter, some libraries give you similarly easy-to-use APIs but are based on code generation instead. This approach is covered in more detail in the code generation libraries section.
you can found the source code inside this answer here

How to handle two calls and the loading controller in Ionic 4

I have a requirement where I have 2 API calls, and I want the first two calls to be there for the first request. And 2nd API call to be there when navigated back.
I am calling 1st API in ngOnInit webhook and 2nd API on ionViewWillEnter webhook.
The issue which I am facing is sometimes my loader doesn’t get dismissed when both of the request complete at the same time.
So the possible solution which I am thinking is that if I could call both APIs on the first load synchronously and thereafter call another API every time the back button is clicked.
NOTE: I am using loaders in my interceptor.
CODE: For interceptor
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// Clone the request to add the new header.
const authReq = req.clone();
this.showLoading();
// send the newly created request
return next.handle(authReq).pipe(catchError((error) => {
if (error.status === 401) {
this._navCtrl.navigateForward('/login');
}
return throwError(error);
}), finalize( () => {
console.log('hi');
this.dismissLoading();
})
);
}
EDIT:
Code to show loader and hide loader:
async showLoading() {
return await this._loadingCtrl.create().then(a => {
a.present();
});
}
async dismissLoading() {
return await this._loadingCtrl.dismiss();
}
In my case, I will create a LoaderService to handle the Loading by myself. The special thing is I will create a flag called isShowing, so if the loading is already showing, we just need to update the loading message by calling presentLoader function again. There will be only one Loading popup show up on your screen.
In your case, I would not recommend to display the Loader in HTTP Interceptor because we cannot handle the HTTP call stack there. Just create a new function that combines all necessary API calls and show/dismiss popup when you start/finish processing the data.
import { LoadingController } from '#ionic/angular';
import { Injectable } from '#angular/core';
#Injectable()
export class LoaderService {
private loading: HTMLIonLoadingElement;
private isShowing = false;
constructor(private loadingController: LoadingController) {}
public async presentLoader(message: string): Promise<void> {
if (!this.isShowing) {
this.loading = await this.loadingController.create({
message: message
});
this.isShowing = true;
return await this.loading.present();
} else {
// If loader is showing, only change text, won't create a new loader.
this.isShowing = true;
this.loading.message = message;
}
}
public async dismissLoader(): Promise<void> {
if (this.loading && this.isShowing) {
this.isShowing = false;
await this.loading.dismiss();
}
}
}
The simple solution would be to make a function call whenever you click the bak button and inside the function you can make a API call.
Instead of linking to the back button you can use ionViewWillEnter, which is called whenever you are about to leave a page but the downside would be it is called every time view is changed regardless of the fact that only when back button is clicked.
Also you should check, is your service singleton and it creates a single instance of ionic-loader. I think in your case more than one instance of loader is being created.
Also instead of calling the loader in interceptor, you can call showLoading() in ionViewWillEnter and hideLoading() in ionViewDidEnter() of your page.
You can create a Singleton Loader Service as shown below.
This service will take care of creating only a single instance of ionic loader.
import { Injectable } from '#angular/core';
import { LoadingController } from '#ionic/angular';
#Injectable({
providedIn: 'root'
})
export class LoaderService {
private loader: HTMLIonLoadingElement;
constructor(private loadingController: LoadingController) {}
async showLoader() {
if (!this.loader) {
this.loader = await this.loadingController.create({ message: 'Loading' });
}
await this.loader.present();
}
async hideLoader() {
if (this.loader) {
await this.loader.dismiss();
this.loader = null;
}
}
}
private loading: HTMLIonLoadingElement;
constructor(public loadingController: LoadingController) { }
public async show(): Promise<void> {
return await this.loadingController.create({
message: 'Please wait...',
spinner: 'crescent'
}).then(a => {
a.present().then(() => {
console.log('presented');
});
});
}
return await this.loadingController.dismiss().then(() =>
console.log('dismissed'));
}`enter code here`

Wicket: tell the browser to scroll to certain tag (anchor)

We are using Wicket and our generated pages are quiet long (a lot of vertical scrolling). Some links or form's onSubmit methods invoke just perform some actions on the database and show the same page again:
public class MyPage extends WebPage {
public MyPage(PageParameters parameters) {
....
final Form<Void> form = new StatelessForm<Void>("formId") {
protected void onSubmit() {
// some database stuff
...
setResponsePage(getClass(), getPageParameters());
}
};
...
}
}
How can I make the setResponsePage invocation cause the browser scroll to the form, so the page is not just showing the top? Maybe some JavaScript-injection?
I think a nice Wicket-y solution combines stuff that is already in Michael's answer, with a Behavior, so you can just add this to your form.
form.add( new ScrollToTopBehavior());
The behaviour itself would like something like this:
public class ScrollToTopBehavior extends Behavior
{
#Override
public void renderHead( Component component, IHeaderResponse response )
{
super.renderHead( component, response );
response.render( JavaScriptHeaderItem.forReference( Application.get().getJavaScriptLibrarySettings().getJQueryReference() ) );
component.setOutputMarkupId( true );
String script = String.format("doSomeJavaScriptStuff('%s')", component.getMarkupId());
response.render( OnDomReadyHeaderItem.forScript( script ) );
}
}
UPDATE:
For scrolling to a specific ID / ANCHOR only once, you can follow this answer:
https://stackoverflow.com/a/3163635/461499
JS of course.
This would be something like (with JQuery usage):
var scrollPosition = $('#scrollToMarkupId').offset().top;
$('html, body').animate({ scrollTop: " + scrollPosition + " }, 'slow');
where scrollToMarkupId is wicket component's markup id, which could be obtained by calling component.getMarkupId() method.
I'm not pro in JS, so you can try to google better impl may be.
Now, about wicket:
1) As for me, I prefer AJAX invocations for such behavior ( note that if you use such approach your page won't be stateless ):
// do not override your form's `onSubmit()` method
final Form<Void> form = new Form<Void>("formId");
// adding ajax behavior with `onSubmit()` method overriding.
form.add ( new AjaxFormSubmitBehavior ("submit")
{
protected void onSubmit ( AjaxRequestTarget target )
{
// your submit logic
// then insert js, descriped above:
target.appendJavaScript ("..." + componentToScroll.getMarkupId() + "..");
}
});
This approach won't reload your page at all but also post your data.
/----------------------------------------------------------------------------------------------------------------------------------/
2) You also could execute JS after page loading, by overriding renderHead method:
public class YourPage extends WebPage
{
...
#Override
public void renderHead ( final IHeaderResponse response )
{
//replace `...` by your script.
response.render ( OnDomReadyHeaderItem.forScript ( "..." );
}
...
}
Such script will be invoked after page is renedered (and setResponsePage method will render your page). You can use this approach for any components and panels too.
I've now use following JavaScript injecting code:
add(new Behavior() {
#Override
public void renderHead(Component component, IHeaderResponse response) {
super.renderHead(component, response);
response.render(new HeaderItem() {
#Override
public Iterable<?> getRenderTokens() {
return Collections.singletonList("javascript-anchor");
}
#Override
public void render(Response response) {
response.write("<script type=\"text/javascript\">\n");
response.write("window.location.href='#rules';\n");
response.write("</script>\n");
}
});
}
});
Feel free to comment (I'm a complete JS-noob with only very limited experience in Wicket).

Async CSLA Calls

The 'standard' CSLA async server calls have typically been structured per the following:
Base class:
public static void GetMyObject(EventHandler<DataPortalResult<MyObject>> callback) {
var dp = new DataPortal<MyObject>();
dp.FetchCompleted += callback;
dp.BeginFetch();
}
ViewModel:
protected override void OnInitialize(object parameter) {
base.OnInitialize(parameter);
base.IsBusy = true;
MyObject.GetMyObject((o, e) => {
if (HasNoException(e)) {
Model = e.Object;
}
base.IsBusy = false;
});
}
With the new async/await features, the format would be something like this:
public async static Task<MyObject> GetMyObject() {
return await DataPortal.FetchAsync<MyObject>();
}
and
protected async override void OnInitialize(object parameter) {
base.OnInitialize(parameter);
base.IsBusy = true;
Model = await MyObject.GetMyObjectAsync();
base.IsBusy = false;
}
Should the callback pattern be considered deprecated at this point, or is it still useful for certain UI technologies? When doing a new project, I'd rather not have those methods in there if I can help it.
Personally, I prefer TAP methods over callbacks in all my code.
With Microsoft.Bcl.Async, most platforms support async. However, there are a few situations where neither TAP nor Task is available, e.g., Windows Phone 7.0, .NET CF, SL 3. I would only use callbacks if I had to support one of those platforms.