I am following up the Heros tutorial from angular 2.0 section.5 services.
The documentation says its not necessary to wrap the this.heroes inside a function
constructor(private heroService: HeroService) { }
this.heroService.getHeroes().then(heroes => this.heroes = heroes);
which doesnt work. and getting error as
Error: TypeError: Cannot read property 'getHeroes' of undefined(…)
Whereas if i use onInit then it works (the completion of the section).
constructor(private heroService: HeroService) {
}
ngOnInit() {
this.getHeroes();
}
getHeroes() {
this.heroService.getHeroes().then(heroes => this.heroes = heroes);
}
Why i am getting the result only while running under ngOnInit?
My understanding is that the component class is a kind of toolbox, where you define properties and methods.
Methods will then respond to Angular hooks - like ngAfterViewInit or ngOnInit - or to events, like click().
Sometimes components need to load data when they are instanciated, in which case you can use ngOnInit or constructor to call your loading method.
You do not directly call methods in your class definition. I think that if you did, it could be an issue when importing a class, or when extending a class.
You don't want the class to go fetch your data each time you import your class; rather, you want to have complete control over when your data will be imported.
Here are the best practices for Angular 2
Related
Thank you all so much! I just started in Kotlin which probably should be called the K language (like C and F), and have found so many solutions here on this site...it's awesome!
I have an independent class file called AppTime.kt and it's declared in the AndroidManifest.xml file:
<application
android:name=".AppTime"
class AppTime : Application() {
fun burntToast(sMsg: String) {
Toast.makeText(this.applicationContext, "!", Toast.LENGTH_LONG).show()
}
}
It doesn't run when called anywhere from a Fragment class:
class FirstFragment : Fragment() {...
AppTime().burntToast()
I've tried every approach using parameters for the Toast following makeText(...
and then to call it from a Fragment with or without context or string parameters.
Is it the type of class I have?
Functions defined inside a class can only be called on an instance of that class, as you already found.
But you cannot simply instantiate an arbitrary Application and expect it to work. Android does a lot of behind-the-scenes setup of framework classes before they are usable. Any Application or Activity that you instantiate yourself is useless. You have to use the instances that are provided to you through the lifecycle of the Activities that get launched in your application.
If you want to call this function from your Fragment, you will have to get an instance of your application, which you can get from its associated Activity. Since the Activity class doesn't know about your specific subclass of Application, you must also cast the application to your specific subclass to be able to call its unique functions. You can get the Activity by using requireActivity().
(requireActivity().application as AppTime).burntToast()
I am using protractor to test an angular app which I configured to restart the browser after each test in conf file. However it leads to session errors. I was able to trace this to a helper class I setup that uses expected conditions.
'use strict';
let EC = browser.ExpectedConditions;
let timeOut = 30000;
class ProHelper {
constructor() {}
async waitForUrl(urlSubstring, time = timeOut) {
let isMatchingUrl = EC.urlContains(urlSubstring);
await browser.wait(isMatchingUrl, time, `Timed out waiting for ${urlSubstring}`);
}
...
}
module.exports = ProHelper
The helper class is used inside the page object classes and in some specs. The first test runs fine. However the second one will fail as soon it uses one of the helper methods. It seems the helper methods are still referencing the original browser instance. I tried declaring EC inside the constructor and inside the methods but I get the same error. Is there any way I can re-initialize the helper class after a browser restart?
I made a few changes to get around the issue.
Removed the use of the helper from the specs. It is now only used in the page object classes.
Second I changed browser.ExpectedConditions; to protractor.ExpectedConditions.
Instead of using restartBrowserBetweenTests I added browser.restart() in afterEach for each spec.
That solved my session issue.
Hi i have 'static class' Utils with only static methods (helpers):
export class Utils {
static doSomethingAndRedirect() {
...doo something...
redirectTo->'/home'
}
}
So how redirectTo code should look like?
You have a wrong approach to the usecase you are trying to solve. Have a look at ngrx/store and ngrx/effects.
In short, you define actions and reducers which modify the state of your app. Next, you can react to different actions with different side-effects (ngrx/effects), for example in my app I have got:
Actions: LoginAction and LoginSuccessAction
Effects: when LoginSuccessAction is triggered, my effect redirects to /dashboard component
This makes for nice separation of concerns:
views display the current state and dispatch actions that change the state
actions specify what happens in the app
reducers specify what changes to state occur for different actions
effects specify what side-effects occur for certain actions
The best solution that I found in my case was just... add parameter 'router' into static function argument list:
static doSomethingAndRedirect(router) {
...doo something...
router.navigateByUrl('home'); // redirect
}
This is a kind of compromise between static helper convenience and non-static "angular way".
I wrote a GUI in ScalaFX whichs works quite well when testing it isolated. Things to mention:
The "real" application itself already has a main method, and only that one should be used to start the application, not the one I get when extending JFXApp. So the call to the main method of JFXApp is done manually, from the outside
It should be possible to pass a data structure to the JFXApp, so I added a setter
The whole startup procedure looks like this:
def main(args: Array[String]) {
...
...
JFXGui.setData(data)
JFXGui.main(Array())
}
The problem:
I cannot draw the contents of the data object as long as the main method of the JFX object is not called, so setData is really just a simple setter method. The idea is that JFXGui should draw the data as soon as possible after JFXGui.main was called. But: how can I realize this inside of JFXGui? Is there something like an "onready"-method?
In the above code, I tried to put the call to the setter after the call to the main method, so that the setter can trigger the drawing. What I hadn't in mind is that JFXGui.main is blocking forever, therefore the call to the setter is unreachable code.
How could I fix this? any help is appreciated, thanks.
edit:
JFXGui is the name of my ScalaFX UI:
object JFXGui extends JFXApp {
private var data: Data = _
def setData(data: Data) {
this.data = data;
}
// tons of ScalaFX related things which visualize the data object
// ...
}
Solution 1 (reusing JFXApp)
The Gui object no longer should be an object, but a class with constructor parameters.
class Gui(data: Data) extends JFXApp {
//your existing code without the field data and the method setData()
}
In the startup class:
new Gui(data).main(Array())
Solution 2 (Custom init)
You do not necessarily have to use JFXApp in order to run your application. I suggest you having a look at the source code of JFXApp.main() and the class AppHelper. They contain ~10 lines of code combined so you can just copy their source code and tailor it to your needs.
Throughout my app I have references to a singleton AMD called hub.js - defined as follows:
// hub.js
define(['services/dataservice'], function (dataservice) {
// list of properties
// dataservice === undefined - why?
}
I reference this from other vms by including it like this:
define(['durandal/app', 'services/dataservice', 'durandal/plugins/router', 'services/hub' ], function (app, dataservice, router, hub) {
But I need access to my dataservice from my hub, as you can see in the first snippet. References to dataservice from within hub are all undefined though, despite using the same exact syntax as the other vms.
If I use a different path than services/dataservice then I get 404 not found, so it seems like the JS sees the file, but isn't loading it into this singleton for some reason.
What's going on?
It was a circular reference:
https://groups.google.com/forum/#!topic/durandaljs/1BePNd8wk7M
http://requirejs.org/docs/api.html#circular