how to access Angular2 component specific data in console? - debugging

Is there any way to access Angular2 specific component specific data in console, for debugging purpose?
Like Angular1 has capability to access its components value in console.

update 4.0.0
StackBlitz example
update RC.1
Plunker example In the browser console on the top-left (filter symbol) select plunkerPreviewTarget (or launch the demo app in its own window) then enter for example
Select a component in the DOM node and execute in the console
ng.probe($0);
or for IE - thanks to Kris Hollenbeck (see comments)
ng.probe(document.getElementById('myComponentId')).componentInstance
Alternative
Hint: enabling debug tools overrides ng.probe()
Enable debug tools like:
import {enableDebugTools} from '#angular/platform-browser';
bootstrap(App, []).then(appRef => enableDebugTools(appRef))
Use above Plunker example and in the console execute for example:
ng.profiler.appRef
ng.profiler.appRef._rootComponents[0].instance
ng.profiler.appRef._rootComponents[0].hostView.internalView
ng.profiler.appRef._rootComponents[0].hostView.internalView.viewChildren[0].viewChildren
I haven't found a way yet to investigate the Bar directive.
A better debug experience is provided by Augury which builds on this API
https://augury.angular.io/
https://www.youtube.com/watch?v=b1YV9vJKXEA
original (beta)
Here is a summary how to do that https://github.com/angular/angular/blob/master/TOOLS_JS.md (dead link and I haven't found a replacement).
Enabling debug tools
By default the debug tools are disabled. You can enable debug tools as follows:
import {enableDebugTools} from 'angular2/platform/browser';
bootstrap(Application).then((appRef) => {
enableDebugTools(appRef);
});
Using debug tools
In the browser open the developer console (Ctrl + Shift + j in Chrome). The top level object is called ng and contains more specific tools inside it.
Example:
ng.profiler.timeChangeDetection();
See also
Angular 2: How enable debugging in angular2 from browser console

First select the element using chrome 'inspect element' and run below method in chrome 'developer console'.
ng.probe($0).componentInstance
You could also use a css selector as shown below.
ng.probe($$('.image-picker')[0]).componentInstance
If you do it often, to make it little easier, have a global shortcut created as below. Now select any DOM element inside the component using 'inspect element' and invoke 'e()' from console
window['e'] = () => eval('ng.probe($0).componentInstance');

Using global scope variable.(any browser)
In ngOnInit() of component file
ngOnInit() {
window['test'] = this;
}
Now we can access instance of that component including services(imported on that component).
If you want to prevent accessing test for let's say production, you can conditionally give access to test like:
constructor(private _configService: ConfigService) {
}
ngOnInit() {
if(_configService.prod) {
window['test'] = this;
}
}
Here _configService means the instance of service used by all components and services.
So variable would be set like:
export class ConfigService {
prod = false;
}

I'm surprised that no one has mentioned Augury here, it's a Chrome plugin that gives you convenient access to all the information in your components, and also makes it easier to see that information in the console directly:
https://augury.rangle.io/

Angular 9+:
Select component root element in developer tools (Inspector), then type in console:
ng.getComponent($0);

Related

Can I prevent obfuscation when debugging my Google Apps Script spreadsheet add-on? [duplicate]

I can't find syntax errors in my JavaScript that is in the Google HTMLService (html window in Google Scripts). My work involves Google Visualizations which requires this. It is my first experience with JavaScript and HTML so I'm quite prone to mistakes making this a distressing problem.
The execution log just shows that the html was run, and I don't where in my code to look for errors. I expect that somewhere would say "error in: line x" or "object not accepted line y" but I just don't know where to look.
I would appreciate any pointers on where to find a solution or how to clarify my question.
You can use your browser's Developers Tools. In Chrome, press the f12 button, OR choose More Tools, Developer Tools, and window will open in your browser that looks like this:
One of the tabs is labeled Console. You can print information to the console by using a:
console.log('This is text: ' + myVariable);
statement.
When the Apps Script macro runs, and serves the HTML to your browser, if there are errors, they will be displayed in the Console Log.
I used the HTML you posted, and got msgs in the console of this:
So, for the JavaScript in a <script> tag of the HTML, you don't look for errors in the Apps Script code editor. You need to use the browsers Developer Tools. The JavaScript in a .gs code file is server side code. It runs on Google's servers. The JavaScript in an HTML tag runs in the users browser on the users computer.
You can also step through client side JavaScript code in your browser.
One problem is, that when the HTML is served, the code is changed.
So the JavaScript in your Apps Script code editor will not look the same as what gets served to the browser. If you view the JavaScript served to the browser, it will look totally different than the code in the Script tag in the original file.
You could also use a code editor that has error checking in it. Net Beans has a free code editor.
Debugging a Google Apps Script web application depends a lot on what Google Apps Script features are used, i.e. if it's created using templated HTML, if the client side communicates with the server side, etc.
As the OP case the Google Apps Script execution log doesn't show any error message, it's very likely that the HtmlOutput was created and it should be possible to inspect the code on the client-side.
Google sends to the client-side a IIFE that inserts into an iframe a satinized version of the HTML/CSS/JavaScript passed to the HtmlService, i.e. the white spacing will not be same, comments will not be included among other changes. Anyway, you might use the dev tools to see the resulting JavaScript and call JavaScript functions from dev tools console, etc.
To execute client-side JavaScript from a Google Apps Script web app, first select the userHtmlFrame(userCodeAppPanel) on the console dropdown selector:
You can even do changes to the client-side JavaScript using the dev tools Elements panel or using JavaScript in the dev tools console, and do other stuff. Just bear in mind that changes done there will not be saved on the Google Apps Script project.
It's worthy to mention that it's possible to debug pure JavaScript using the Google Apps Script editor. The easier way is to put the JavaScript code in a .gs file and use HtmlTemplate to create the HtmlOutput object of the web application together with: ScriptApp.getResource(name).getDataAsString(). Also this approach will help to test the JavaScript code using desktop tools, will help to make it easier to fix "Malformed" errors caused by missing / misplaced <,>,",',(,),:,; and take advantage of the intellisense features for JavaScript that aren't available in the .html files.
Sample of a web application having the client-side JavaScript on a .gs file instead of on a .html file. The client-side JavaScript is in the javascript.js.gs file. In this overly simplified example, the function to be tested require parameters. This makes that the function cannot be run directly from the Editor toolbar, so there is couple of "test" functions on the test.gs file that set the required parameters and call the function that we want to debug.
Code.gs
/**
* Respond to HTTP GET request. Returns a htmlOutput object.
*/
function doGet(e){
return HtmlService.createTemplateFromFile('index')
.evaluate()
.setTitle('My web app');
}
/**
* Returns the file content of a .gs or .html Google Apps Script file.
*
* #param {filename} Google Apps Script file name. It should not include the .gs or .html file extension
*/
function include(filename){
const [name, sufix] = filename.split('.');
switch(sufix){
default:
return HtmlService.createHtmlOutputFromFile(name).getContent();
case 'js':
const content = ScriptApp.getResource(name).getDataAsString();
return `<script>${content}</script>`;
}
}
index.html
<!DOCTYPE html>
<html>
<head>
<?!= include('stylesheet.css') ?>
</head>
<body>
<p>Add here some content</p>
<?!= include('javascript.js') ?>
</body>
</html>
javascript.js.gs
/**
* Arithmetic addition of two operands. Validates that both operands are JavaScript numbers.
*
* #param {number} a Left addition operand
* #param {number} a Right addition operand
*/
function addition(a,b){
if(typeof a !== 'number') || typeof b !== 'number') throw new Error('Operands should be numbers');
return a + b;
}
tests.gs
/**
* Passing two numbers. Expected result: 2.
*/
function test_addition_01(){
const a = 1;
const b = 1;
const result = addition(a,b);
console.log(result === 2 ? 'PASS' : 'FAIL');
}
/**
* Passing one number and one string. Expected result: Custom error message.
*/
function test_addition_02(){
const a = 1;
const b = '1';
try{
const result = addition(a,b);
} catch(error) {
console.log(error.message === 'Operands should be numbers' ? 'PASS' : 'FAIL');
}
}
Note: ScriptApp.getResource can't pull files from libraries even when including this method on the library
For debugging JavaScript that makes use of other technologies, i.e. document.getElementById(id) one option is to dev tools console or using try... catch and call some function from the server side, google.script.run, for logging errors on the execution logs.
To debug a JavaScript that calls JavaSCript libraries, you might copy the libraries code into one or multiple .gs files or load it into the server side by using UrlFetchApp and eval (see How to load javascript from external source and execute it in Google Apps Script)

Xamarin Forms WebView open external link

I have a webview inside my application and when an external link is clicked (that in normal browser is open in a new tab), I can't then go back to my website.
It is possible when a new tab is open to have the menu closed that tab like Gmail do ?
The objective is that, whenever a link is clicked, the user would have the choice to choose which option to view the content with, e.g. Clicking a link would suggest open youtube app or google chrome. The purpose is to appear the google chrome option
Or what suggestions do you have to handle this situation ?
If I understood you correctly, you want to have the option to select how to open the web link - inside your app, or within another app's (browser) context.
If this is correct, then you can use Xamarin.Essentials: Browser functionality.
public async Task OpenBrowser(Uri uri)
{
await Browser.OpenAsync(uri, BrowserLaunchMode.SystemPreferred);
}
Here the important property is the BrowserLaunchMode flag, which you can learn more about here
Basically, you have 2 options - External & SystemPreferred.
The first one is clear, I think - it will open the link in an external browser.
The second options takes advantage of Android's Chrome Custom Tabs & for iOS - SFSafariViewController
P.S. You can also customise the PreferredToolbarColor, TitleMode, etc.
Edit: Based from your feedback in the comments, you want to control how to open href links from your website.
If I understood correctly, you want the first time that you open your site, to not have the nav bar at the top, and after that to have it. Unfortunately, this is not possible.
You can have the opposite behaviour achieved - the first time that you open a website, to have the nav bar and if the user clicks on any link, to open it externally (inside a browser). You have 2 options for this:
To do it from your website - change the a tag's target to be _blank like this;
To do it from your mobile app - create a Custom renderer for the WebView. In the Android project's renderer implementation, change the Control's WebViewClient like so:
public class CustomWebViewClient : WebViewClient
{
public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, IWebResourceRequest request)
{
Intent intent = new Intent(Intent.ActionView, request.Url);
CrossCurrentActivity.Current.StartActivity(intent);
return true;
}
}

NativeScript adding xml namespace on Page tag

I'm new to NativeScript. I have created a new project using the Angular Blank template. The navigation is done using page-router-outlet. I want to include a xmlns attribute on the page level. As far as i can see and understand the entire code is rendered inside a global page attribute. I've seen that I can modify the page properties by injecting the Page in a component and changing it's properties, but how can I do this for xmlns?
Best regards,
Vlad
To register a UI component in Angular based application you should use registerElement and not XML namespaces (which is a concept used in NativeScript Core). Nowadays most plugin authors are doing this job for you, but still, some of the plugins are not migrated to use the latest techniques so in some cases, we should manually register the UI element.
I've created this test applicaiton which demonstrates how to use nativescript-stripe in Angular. Here are the steps to enable and use the plugin.
Installation
npm i nativescript-stripe --save
Register the UI element in app.module.ts as done here
import { registerElement } from "nativescript-angular/element-registry";
registerElement("CreditCardView", () => require("nativescript-stripe").CreditCardView);
Add the following in main.ts as required in the plugin README
import * as app from "tns-core-modules/application";
import * as platform from "tns-core-modules/platform";
declare const STPPaymentConfiguration;
app.on(app.launchEvent, (args) => {
if (platform.isIOS) {
STPPaymentConfiguration.sharedConfiguration().publishableKey = "yourApiKey";
}
});
Use the plugin in your HTML (example)
<CreditCardView id="card"></CreditCardView>

Best way to control firefox via webdriver

I need to control Firefox browser via webdriver. Note, I'm not trying to control page elements (i.e. find element, click, get text, etc); rather I need access to Firefox's profiler and force gc (i.e. I need firefox's Chrome Authority and sdk). For context, I'm creating a micro benchmark framework, not running a normal webdriver test.
Obviously raw webdriver won't work, so what I've been trying to do is
1) Create a firefox extension/add-on that does what I need: i.e.
var customActions = function() {
console.log('calling customActions.')
// I need to access chrome authority:
var {Cc,Ci,Cu} = require("chrome");
Cc["#mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler);
Cu.forceGC();
var file = require('sdk/io/file');
// And do some writes:
var textWriter = file.open('a/local/path.txt', 'w');
textWriter.write('sample data');
textWriter.close();
console.log('called customActions.')
};
2) Expose my customActions function to a page:
var mod = require("sdk/page-mod");
var data = require("sdk/self").data;
mod.PageMod({
include: ['*'],
contentScriptFile: data.url("myscript.js"),
onAttach: function(worker) {
worker.port.on('callCustomActions', function() {
customActions();
});
}
});
and in myscript.js:
exportFunction(function() {
self.port.emit('callCustomActions');
}, unsafeWindow, {defineAs: "callCustomActions"});
3) Load the xpi during my webdriver test, and call out to global function callCustomActions
So two questions about this process.
1) This entire process is very roundabout. Is there a better practice for talking to a firefox extension via webdriver?
2) My current solution isn't working well. If I run my extension via cfx run directly (without webdriver) it works as expected. However, neither the sdk nor chrome authority do anything when running via webdriver.
By the way, I know my function is being called because the log line "calling customActions." and "called customActions." both do print.
Maybe there are some firefox preferences that I need to set but haven't?
It may be that you do not need the add-on at all. Mozilla uses Marionette for test automation of Firefox OS amongst other things:
Marionette is an automation driver for Mozilla's Gecko engine. It can
remotely control either the UI or the internal JavaScript of a Gecko
platform, such as Firefox or Firefox OS. It can control both the
chrome (i.e. menus and functions) or the content (the webpage loaded
inside the browsing context), giving a high level of control and
ability to replicate user actions. In addition to performing actions
on the browser, Marionette can also read the properties and attributes
of the DOM.
If this sounds similar to Selenium/WebDriver then you're correct!
Marionette shares much of the same ethos and API as
Selenium/WebDriver, with additional commands to interact with Gecko's
chrome interface. Its goal is to replicate what Selenium does for web
content: to enable the tester to have the ability to send commands to
remotely control a user agent.

Dynamically changing proxy in Firefox with Selenium webdriver

Is there any way to dynamically change the proxy being used by Firefox when using selenium webdriver?
Currently I have proxy support using a proxy profile but is there a way to change the proxy when the browser is alive and running?
My current code:
proxy = Proxy({
'proxyType': 'MANUAL',
'httpProxy': proxy_ip,
'ftpProxy': proxy_ip,
'sslProxy': proxy_ip,
'noProxy': '' # set this value as desired
})
browser = webdriver.Firefox(proxy=proxy)
Thanks in advance.
This is a slightly old question.
But it is actually possible to change the proxies dynamically thru a "hacky way"
I am going to use Selenium JS with Firefox but you can follow thru in the language you want.
Step 1: Visiting "about:config"
driver.get("about:config");
Step 2 : Run script that changes proxy
var setupScript=`var prefs = Components.classes["#mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
prefs.setIntPref("network.proxy.type", 1);
prefs.setCharPref("network.proxy.http", "${proxyUsed.host}");
prefs.setIntPref("network.proxy.http_port", "${proxyUsed.port}");
prefs.setCharPref("network.proxy.ssl", "${proxyUsed.host}");
prefs.setIntPref("network.proxy.ssl_port", "${proxyUsed.port}");
prefs.setCharPref("network.proxy.ftp", "${proxyUsed.host}");
prefs.setIntPref("network.proxy.ftp_port", "${proxyUsed.port}");
`;
//running script below
driver.executeScript(setupScript);
//sleep for 1 sec
driver.sleep(1000);
Where use ${abcd} is where you put your variables, in the above example I am using ES6 which handles concatenation as shown, you can use other concatenation methods of your choice , depending on your language.
Step 3: : Visit your site
driver.get("http://whatismyip.com");
Explanation:the above code takes advantage of Firefox's API to change the preferences using JavaScript code.
As far as I know there are only two ways to change the proxy setting, one via a profile (which you are using) and the other using the capabilities of a driver when you instantiate it as per here. Sadly neither of these methods do what you want as they both happen before as you create your driver.
I have to ask, why is it you want to change your proxy settings? The only solution I can easily think of is to point firefox to a proxy that you can change at runtime. I am not sure but that might be possible with browsermob-proxy.
One possible solution is to close the webdriver instance and create it again after each operation by passing a new configuration in the browser profile
Have a try selenium-wire, It can even override header field
from seleniumwire import webdriver
options = {
'proxy': {
"http": "http://" + IP_PORT,
"https": "http://" + IP_PORT,
'custom_authorization':AUTH
},
'connection_keep_alive': True,
'connection_timeout': 30,
'verify_ssl': False
}
# Create a new instance of the Firefox driver
driver = webdriver.Firefox(seleniumwire_options=options)
driver.header_overrides = {
'Proxy-Authorization': AUTH
}
# Go to the Google home page
driver.get("http://whatismyip.com")
driver.close()

Resources