I'm trying to create a dialog box system in typescript.
The intended use would be that a caller would do something like this;
dialogBox.showDialog().then((result: DialogResult) => {
// Handle the dialog result
});
My DialogBox class would probably have some methods like this;
private promise : Q.Promise<DialogResult>;
public showDialog() : Q.Promise<DialogResult>{
this.promise = ... // How to create this promise?
return this.promise;
}
public void setResult(result : DialogResult){
// What to do here?
}
Whenever the user clicks a button in the dialog, something like this would be called;
dialogBox.setResult(theResult);
This should then resolve/fulfill the promise created by the showDialog method.
But I can't really figure out if this is possible with Q and so, how to implement the (promise-related parts of) showDialog and setResult. Anyone got any ideas?
Update for completeness; Thanks to Bergi, here's my final, working code. Ended up using a deferred
export class DialogBox implements INotification {
private deferred: Q.Deferred<DialogResult>;
constructor(public message: string,
public header: string,
public buttons?: DialogResult[]) {
}
public showDialog(): Q.Promise<DialogResult> {
this.deferred = Q.defer<DialogResult>();
// My logic for displaying the box goes here
return this.deferred.promise;
}
public setResult(result: DialogResult) {
this.deferred.resolve(result);
}
}
You'd either use a deferred that is stored as a private field of your class, or you'd use the Promise constructor (which is preferred).
private deferred : Q.Deferred<DialogResult>;
public showDialog() : Q.Promise<DialogResult>{
this.deferred = Q.defer();
// create dialog
return this.deferred.promise;
}
public void setResult(result : DialogResult){
this.deferred.resolve(result);
}
public showDialog() : Q.Promise<DialogResult>{
return new Q.Promise(function(resolve) {
// create dialog
setResult = resolve;
// call it somewhere
})
}
Related
I want to do something like this in a razor page:
#if (currentwidth<x)
{
le code
}
else
{
le other code
}
I have added javascript file and connected it to a utility service which works when I get the static width (which I tested).
js:
export function getCurrentWidth() {
return window.addEventListener("resize", () => {
window.innerWidth;
});
}
UtilityService method:
public async Task<double> GetCurrentWidth()
{
var m = await GetModule();
var result = await m.InvokeAsync<double>("getCurrentWidth");
return result;
}
Razor file:
double width;
protected async override Task OnInitializedAsync()
{
width = await utilityService.GetCurrentWidth();
}
Thus the problem is I can't call it from OnInitailzedAsync since this function only fired once, so I need a function that constantly checks the GetCurrentWIdth() method to check for resize.
Is there another way of doing this in blazor or what method could I use/ Thank you in advance.
First of all I'd like to point out that you may not have to solve your problem with javascript/C# code. If it's something in the html that you want to manipulate, you may just be better of using css. But I'll leave that up to you.
If however you truly need the window width like you mentioned above, then I would recommend registering a listener to the window (as you've already done) and have that listener call a dotnet function. Doing this with static methods is quite easy, but for instance component this can be a bit trickier as you have to pass an object reference of the current object.
The [JsInvokable] indicates that this method can be called from javascript, which allows communication from the javascript event listener to dotnet.
CSharpFromJs.razor.cs
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using System.Threading.Tasks;
public partial class CSharpFromJS
{
private DotNetObjectReference<CSharpFromJS> _objectReference;
public int WindowWidth { get; set; }
[Inject]
public IJSRuntime JSRuntime { get; set; }
protected override void OnInitialized()
{
_objectReference = DotNetObjectReference.Create(this);
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await InitWindowWidthListener();
}
}
[JSInvokable]
public void UpdateWindowWidth(int windowWidth)
{
WindowWidth = windowWidth;
StateHasChanged();
}
private async Task InitWindowWidthListener()
{
await JSRuntime.InvokeVoidAsync("AddWindowWidthListener", _objectReference);
}
public async ValueTask DisposeAsync()
{
await JSRuntime.InvokeVoidAsync("RemoveWindowWidthListener", _objectReference);
_objectReference?.Dispose();
}
}
CSharpFromJs.razor
#implements IAsyncDisposable
<h1>Window width: #WindowWidth</h1>
Javascript
// Manages the registered event listeners so they can be disposed later
let windowEventListeners = {};
function AddWindowWidthListener(objReference) {
let eventListener = () => UpdateWindowWidth(objReference);
window.addEventListener("resize", eventListener);
windowEventListeners[objReference] = eventListener;
}
function RemoveWindowWidthListener(objReference) {
window.removeEventListener("resize", windowEventListeners[objReference]);
}
function UpdateWindowWidth(objReference) {
objReference.invokeMethodAsync("UpdateWindowWidth", window.innerWidth);
}
The only thing you should be careful with is when a component is disposd. You should remove the registered handlers in the DisposeAsync function to ensure that they're not still registered to prevent memory leaks.
This link might provide some better instructions on how to use this, but they don't explain the part about disposing handlers.
Note: This only works in .net5 and later, as IAsyncDisposable was not yet implemented for component before that. If for some reason you're working with an earlier version, you could call it using IDisposable. But this could potentially cause deadlocks, so I would not recommend it.
For me works the NuGet package BlazorPro.BlazorSize
Implement the method:
async void WindowResized(object _, BrowserWindowSize window){}
and all necessary Dependencies (see description).
I looking for a way to inherit from WebElement object that webdriverio returns, without monkey-patching and with TS types support (autocompletion is a must). Is there a way to do something like this?
class Checkbox extends WebdriverIOWebElement {
constructor() {
super($('div'))
}
// overriding base method
isDisplayed(): boolean {
// blabla some new logic here
}
check() {
if(!this.isChecked()) {
this.click()
}
}
uncheck() {
if(this.isChecked()) {
this.click()
}
}
}
Lets take an example , When we have a New Tag (my-app) in HTML and we have to build a case to Login using webdriverIO ,
Assume this is the HTML :
What we would do is using the component object pattern , component object pattern attempts to reduce that repetition and move the component's api into an object of its own. We know that in order to interact with an element's shadow DOM, we first need the host element. Using a base class for your component objects makes this pretty straightforward.
Here's a bare-bones component base class that takes the host element in its constructor and unrolls that element's queries up to the browser object, so it can be reused in many page objects (or other component objects), without having to know anything about the page itself.
class Component {
constructor(host) {
const selectors = [];
// Crawl back to the browser object, and cache all selectors
while (host.elementId && host.parent) {
selectors.push(host.selector);
host = host.parent;
}
selectors.reverse();
this.selectors_ = selectors;
}
get host() {
// Beginning with the browser object, reselect each element
return this.selectors_.reduce((element, selector) => element.$(selector), browser);
}
}
module.exports = Component;
then what we would do is , We will write a subclass for our app-login component:
const Component = require('./component');
class Login extends Component {
get usernameInput() {
return this.host.shadow$('input #username');
}
get passwordInput() {
return this.host.shadow$('input[type=password]');
}
get submitButton() {
return this.login.shadow$('button[type=submit]');
}
login(username, password) {
this.usernameInput.setValue(username);
this.passwordInput.setValue(password);
this.submitButton.click();
}
}
module.exports = Login;
Finally, we can use the component object inside our login page object:
const Login = require('./components/login');
class LoginPage {
open() {
browser.url('/login');
}
get app() {
return browser.$('my-app');
}
get loginComponent() {
// return a new instance of our login component object
return new Login(this.app.$('app-login'));
}
}
Now this component object can now be used in tests for any page or section of your app that uses an app-login web component, without having to know about how that component is structured. If you later decide to change the internal structure of the web component, you only need to update the component object.
Now we apply the same approach with the Check Box Component by using Shadow Dom Support :
public class CheckBox extends Component {
public CheckBox(element) {
this.element = element;
}
get checkBoxSelector() {
return this.host.shadow$(element);
}
get void toggle() {
checkBoxSelector().click();
}
get void check() {
if (!isChecked()) {
toggle();
}
}
get void uncheck() {
if (isChecked()) {
toggle();
}
}
get boolean isChecked() {
return checkBoxSelector().isSelected();
}
}
Then We can write a Check Box Controller component that can get the instance of check box using id and verify what every is necessary.
const CheckBox= require('./components/CheckBox');
class CheckBoxController{
open() {
browser.url('/login');
}
get checkboxComponent() {
// Using this we can verify whether the Specific Check Box has been Selected or Not
let element = browser.$('[id="lpagecheckbox"]');
return new CheckBox(element);
}
}
Note :
Please bear this is not the actual code , This is just a part of the template which can help us to move towards the solution of the Problem .
Source Contends :
https://webdriver.io/docs/api/element/isSelected.html
https://webdriver.io/blog/2019/02/22/shadow-dom-support.html
https://webdriver.io/blog/2019/04/03/react-selectors.html
https://webdriver.io/docs/pageobjects.html
Moreover if we are using Selenium Webdriver , This can help us to Achieve it
Here we have an interface which actually combines all the webdriver interfaces , then we create a Specific implementation by inheriting the Element Class , finally Lets assume of any component you need we should be inheriting and using it with its own implementation , In this case lets assume the Check box that should be inherited from then Element Implementation Class and finally a Cranky way of using it by instantiating the object. CheckBox cb = new CheckBox(element);cb.uncheck();
Step 1:
Create an Interface that combines all of the WebDriver interfaces:
public interface Element extends WebElement, WrapsElement, Locatable {}
Step 2:
Element Implementation Inheriting the element class:
public class ElementImpl implements Element {
private final WebElement element;
public ElementImpl(final WebElement element) {
this.element = element;
}
#Override
public void click() {
element.click();
}
#Override
public void sendKeys(CharSequence... keysToSend) {
element.sendKeys(keysToSend);
}
// And so on, delegates all the way down...
}
Step 3:
Consider any component you use , Lets assume Check Box in this case
public class CheckBox extends ElementImpl {
public CheckBox(WebElement element) {
super(element);
}
public void toggle() {
getWrappedElement().click();
}
public void check() {
if (!isChecked()) {
toggle();
}
}
public void uncheck() {
if (isChecked()) {
toggle();
}
}
public boolean isChecked() {
return getWrappedElement().isSelected();
}
}
Way of Using It :
CheckBox cb = new CheckBox(element);
cb.uncheck();
If you want More Clear way of Implementing Something Like this : refer the third Link
public class Part2ExampleTest {
private final WebDriver driver;
#FindBy(id = "checkbox")
CheckBox checkBox;
protected Part2ExampleTest(WebDriver driver) {
this.driver = driver;
}
protected static Part2ExampleTest initialize(WebDriver driver) {
return ElementFactory.initElements(driver, Part2ExampleTest.class);
}
#Test
public void simple() {
WebDriver driver = new FirefoxDriver();
Part2ExampleTest page = initialize(driver);
PageLoader.get(driver, "forms.html");
Assert.assertFalse(page.checkBox.isChecked());
page.checkBox.check();
Assert.assertTrue(page.checkBox.isChecked());
driver.close();
}
}
Sources :
Extend Selenium WebDriver WebElement?
http://elisarver.com/2012/12/09/wrapping-webelement-1/
http://elisarver.com/2012/12/10/wrapping-webelement-2
IWebElement is an interface that you can just implement inside your driver class.
I have a webview. I want to call JS function from Java and assign return value to a variable.
This line from java calls getUserDetails() function of JavaScript.
webview.loadUrl("javascript:window.getUserDetails()");
This is the getUserDetails function in javascript which returns a string
window.getUserDetails = function(){
return "username";
}
I want to achieve something like this.
String user = webview.loadUrl("javascript:window.getUserDetails()");
How can I able to achieve this?
You have to change the way you are calling that method.
webview.loadUrl("javascript:alert(window.getUserDetails())");
and while handling the alert your returned value will be there.
For more info please follow this link
As per the comment you can do this in following way.
String mUserName;
String getUserName(){
runOnUiThread(new Runnable() {
#Override
public void run() {
webView.loadUrl("javascript:android.onData(window.getUserDetails())");
}
});
return mUserName;
}
#JavascriptInterface
public void onData(String value) {
mUserName = value;
}
WebView#evaluateJavascript is the recommended way to do this asynchronously. If you want something which feels synchronous, you can try using Futures to wait for the callback:
final SettableFuture<String> jsFuture = SettableFuture<>.create();
webView.evaluateJavaScript("window.getUserDetails()", new ValueCallback<String>() {
#Override
public void onReceiveValue(String value) {
jsFuture.set(value);
}
});
String value = jsFuture.get();
Greetings fellow Earthicans,
The following code is used on my website: brianjenkins94.me in order to handle baseline navigation functionality and while it was working previously I decided to leverage the class-based approach provided by the TypeScript Language in order to structure my code in a more readable fashion. In doing so I seem to have broken the functionality and now all #nav.on("click") events trigger the error Uncaught TypeError: Cannot read property 'removeClass' of undefined on Line 54 (see comment in code).
If anyone could identify why this code is nonfunctional or perhaps provide some insight as to whether there is a better way of going about doing this, (I'm really interested in proper design and right practice, the bug is just a convenient excuse to make a post and get input) it would be greatly appreciated.
Thanks ahead of time,
Brian
/// <reference path="jquery.d.ts" />
"use strict";
class Main {
//private SERVERNAME: string = "http://brianjenkins94.me/";
//private DOCUMENTROOT: string = "https://rawgit.com/brianjenkins94/local.blog.com/master/"
public init(): void {
$(function(): void {
var Nav: Navigation = new Navigation($("body"), $("#nav"), $("a[href=\"#nav\"]"));
Nav.init();
});
}
}
class Navigation {
private body: JQuery;
private nav: JQuery;
private navToggle: JQuery;
private navClose: JQuery = $("<a></a>");
constructor(bodyInit: JQuery, navInit: JQuery, navToggleInit: JQuery) {
this.body = bodyInit;
this.nav = navInit;
this.navToggle = navToggleInit;
// Create navClose element
this.navClose.attr({
href: "#",
tabIndex: 0
});
(this.navClose).addClass("close");
(this.nav).append(this.navClose);
};
public init(): void {
this.disablePropogation();
this.clickListener(this.body);
this.clickListener(this.navToggle);
this.clickListener(this.navClose);
this.clickListener(this.nav);
this.keyCodeListener();
}
private disablePropogation(): void {
(this.nav).on("click touchend", function(event: Event): void {
event.stopPropagation();
});
}
private clickListener(target: JQuery): void {
(target).on("click touchend", function(): void {
if (!(target === (this.body))) {
event.preventDefault();
event.stopPropagation();
if (target === this.navToggle) {
(this.nav).toggleClass("visible");
return;
}
}
(this.nav).removeClass("visible"); // They call me, line 54
});
}
private keyCodeListener(): void {
$(window).on("keydown", function(event: JQueryKeyEventObject): void {
if (event.keyCode === 27) {
(this.nav).removeClass("visible");
}
});
}
}
var main: Main = new Main();
main.init();
this is of the wrong type (window) and not the instance of the class. The best way to fix It is by using an Arrow function to capture the this reference like below:
private clickListener(target: JQuery): void {
(target).on("click touchend", () => {
if (!(target === (this.body))) {
event.preventDefault();
event.stopPropagation();
if (target === this.navToggle) {
(this.nav).toggleClass("visible");
return;
}
}
(this.nav).removeClass("visible"); // They call me, line 54
});
}
Check out the generated code on what it actually does. If you also want to use this provided by jQuery (the element in this case) you can also do
var that = this;
Right above the on call and use that for the class and this for your jQuery target. This is similar to what the arrow function generates but that generates _this instead of "that".
edit if you need to keep TSLint happy you should probably do () :void => { in the arrow function
The basic idea is to prevent double clicks. I'm using html <button> to call a function when clicked, which makes an ajax call. Native <button> behaviour is prevented with event.preventDefault(), that means no form should be submitted. Also, i'm using TypeScript:
private form: JQuery;
...
private getTargetAndCallAjax(): void {
var target: string = this.form.find("form").data("target");
this.form.find("button[type='submit']").on("click", (event)=> {
event.preventDefault();
this.callAjax(target);
});
}
private callAjax(target: string): void {
...
}
As , i've implemented _.debounce as:
private form: JQuery;
...
private getTargetAndCallAjax(): void {
var target: string = this.form.find("form").data("target");
this.form.find("button[type='submit']").on("click", (event) => {
event.preventDefault();
var ajaxCall = function () { this.callAjax(target) };
_.debounce(ajaxCall, 1000, true);
});
}
private callAjax(target: string): void {
...
}
The goal is to call this.ajaxCall(target) every 1 second, if multiple <button> clicks detected. Unfortunately, function this.ajaxCall(target) gets never called. Any ideas?
It is becuase you have the wrong this context in ajaxCall. Fix:
var ajaxCall = () => { this.callAjax(target) };
PS: why: https://www.youtube.com/watch?v=tvocUcbCupA&hd=1
Additionally _.debounce returns a debounced function that you need to call. So the complete code:
var debouncedAjaxCall = _.debounce(() => this.callAjax(target), 1000, true);
debouncedAjaxCall();