AngularJS 2: concurrent data access to proprety in an injectable class - angularjs

The whole matter come up when we had a shared component #Injectable. Every component in the app.module.ts can inject it into his own constructor.
export class SimpleComponent {
constructor (private sharedComponent : SharedComponent){}
}
I write a method in this class SimpleComponent to set a proprety at the shared component:
setPropretyAtSharedComponent {
this.sharedComponent.setProprety("proprety")
}
Presuming that the SharedComponent held:
#Injectable()
export class SharedComponent {
proprety :any
constructor() {}
}
setProprety (proprety){
this.proprety = proprety;
}
At this point every thing is OK.
So I was wondering if I had two components at the same page which sets the proprety value of the SharedComponent at meanwhile (concurent access) how I can handle that?

I guess that's taken care of by the DI framework once you define your Injectable service in providers in your module. Once your service is defined in the module, you can inject it in different components as a singleton.
You can refer to these docs:https://angular.io/docs/ts/latest/guide/dependency-injection.html

Related

How to define SecureLS in React.js to secure session details like JWT token?

I have gone through the git for SecureLS, but I find it difficult to define SecureLS in React.
var ls = new SecureLS({ encodingType: 'aes' })
How can I define like this in React.js class component?
With React class components, you can create instances of class within componentDidMount method in class components and store it in class variable
class App extends React.Component {
componentDidMount() {
this.ls = new SecureLS({ encodingType: 'aes' })
}
}
Now you can use ls anywhere in your class with this.ls
P.S. Do keep in mind context issues whenever you use this.ls in class functions. The this inside class functions must refer to the class instance

What is the equivalent of Java singleton in React Native?

Actually I am a Android Native Developer. I am new to React-Native. In Java i keep the users data and others data in Singleton Class and access from other activities. Then how i achieve this process in React native for access data's from other components or any alternative of singleton in React native.
I just try this but i received the error like getInstance() not defined.
class AppDelegate {
log = "This is AppDelegate";
static myInstance = null;
static getInstance() {
if (AppDelegate.myInstance == null) {
AppDelegate.myInstance = new AppDelegate();
}
return this.myInstance;
}
}
Thank you.
React is UI library, this isn't its responsibility. The question affects any JavaScript application, not only React.
JavaScript modules and ES modules in particular are evaluated only once under normal circumstances, this makes exports singletons:
// exported for extensibility
export class AppDelegate {...}
// a singleton
export default new AppDelegate;
Singleton class is potentially an antipattern in JavaScript. If there's a need for one object, it could be written as object literal.
Imports are cached, so if you export a class, the class will be cached, if you export an instance, the instance will be cached
If you need a singleton don't use a class at all.
Export the methods as a function instead.
// File app-delegate.js
let privateIstanceValue;
export const method1 = () => //do something;
export const method2 = () => //do something again;
Import using import * as
import * as appDelegate from './app-delegate.js';

Angular 2 Access input value of a different routed component via ngOnInit?

I have a search bar in app.component.ts that has an input value.
results.component.ts is embedded with a router-outlet in app.component.html
When results.component.ts is the current activated route, the search works fine and so do the results.
However, if someone clicks on a result, results.component.ts is replaced with a different component view detail.component.ts (it provides them with more information about the result.)
On detail.component.ts I have a "back to results" link setup with a routerLink='/'. And mind you, the search query is still present in the search bar because that view never gets replaced.
When this back button is clicked, results.component.ts reloads and fires ngOnInit.
The problem: I can't access the value of the search string in app.component.ts from results.component.ts ngOnInit to repopulate the results. I've tried almost everything I can think of.
I already have a service built, but I don't know how to set it up to communicate that value, if that is the solution.
Updated with code
app.component.html
//other html
<input placeholder="What do you want to learn?" name="searchStr" [(ngModel)]="searchStr" (keyup.enter)="searchCourse($event)">
interaction-service.service.ts:
import { Injectable } from '#angular/core';
import { Subject } from 'rxjs/Subject';
#Injectable()
export class InteractionService {
// Observable string sources
private searchStr = new Subject<string>();
// Observable string streams
searchStr$ = this.searchStr.asObservable();
sendString(searchString: string) {
this.searchStr.next(searchString);
}
}
app.component.ts:
//other imports
import {InteractionService} from './interaction-service.service';
#Component({
selector: 'my-app',
templateUrl: 'app.component.html',
providers: [CourseService, InteractionService]
})
export class AppComponent implements OnInit {
searchStr: string;
constructor(private _courseService: CourseService, private _interactionService: InteractionService, private router: Router) {
}
ngOnInit() {
}
searchCourse(event) {
this._interactionService.sendString(event.target.value);
this.router.navigateByUrl('/');
}
}
course-listings.component.ts (I referred to this as results above)
// other imports
import {Subscription} from 'rxjs';
import {InteractionService} from '../interaction-service.service';
#Component({
selector: 'app-course-listings',
templateUrl: './course-listings.component.html',
providers: [CourseService],
})
export class CourseListingsComponent implements OnInit {
//some other properties defined
#Input() searchStr: string;
subscription: Subscription;
constructor(private _courseService: CourseService, private _interactionService: InteractionService) {
this.subscription = this._interactionService.searchStr$.subscribe(
courses => {
this.searchStr = courses;
// code for returning results here..
}
);
}
ngOnInit() {
}
}
Your right that you want to use a service. Services are singletons so setting in one component and getting from another will return the passed value.
To get a service to work you need to create the service then add it to your app module. Then in the constructor for your component you add it so the dependency injection can add it to the component for you. The constructor looks like this.
constructor( private router: Router){}
Each component should have a reference in its constructor and the service singleton is shared.
interaction-service.service.ts:
import { Injectable } from '#angular/core';
import { Subject } from 'rxjs/Subject';
#Injectable()
export class InteractionService {
sharedString = "";
}
app.component.ts:
import {InteractionService} from './interaction-service.service';
#Component({
selector: 'my-app',
templateUrl: 'app.component.html',
providers: [CourseService, InteractionService]
})
export class AppComponent implements OnInit {
constructor(private _courseService: CourseService, private _interactionService: InteractionService, private router: Router) {
}
ngOnInit() {
this.__interactionService.sharedString = "Some value";
}
searchCourse(event) {
this._interactionService.sendString(event.target.value);
this.router.navigateByUrl('/');
}
}
I'm going to leave the rest of the code out. The above example should be enough. Simply make the injected interaction service available and set and get the values at will. The service values will persist until there is a browser context change. Last thing I want to mention is when routing call the router like this
this.router.navigate(["url", someParam]);
this will preserve context and not cause a browser context switch when moving between components.

Typescript: Make class in function known to ts

So I have my classes defined in angular factory functions:
export default function ($resource, $http:angular.IHttpService) {
return class Account{}
}
I also have a all.ts where my typings of definitelytyped are included. When I want to use Account in another class, I inject it with:
class AccountsController {
public static $inject = ['Account'];
constructor(public Account:Account){}
}
However, Account is unknown and even if I add the factory file to all.ts references, it does not find it.
How can I make Account known to typescript, ideally without defining the interface again (as it is already defined through the class, isn't it?).
I usually do it like this:
export function theService(...): theService {
return {
theServiceMethod1: function(id) {
}
}
export declare interface theService {
theServiceMethod1(id): void;
....
}
The same can be applied to a class as well. The class members are known, but the return type of the exported functions are not as far as I can tell.

play framework route that matches all

I'm working on an angular app using play framework for my rest-services. Everything in the public folder is an angular app (stylesheets, javascripts, images and html). I want every request that is not for something in the stylesheets, javascripts, templates or images folder to be routed to the index.html page. This is so that angular routing can take over from there...
As a side note i can mention that I am going to place every restservice under /services/ which links to my own java controllers.
Is it possible in play framework 2.3.4 to define a route that catches all without having to use the matching elements?
This is my route defs so far:
GET / controllers.Assets.at(path="/public", file="index.html")
GET /stylesheets/*file controllers.Assets.at(path="/public/stylesheets", file)
GET /javascripts/*file controllers.Assets.at(path="/public/javascripts", file)
GET /templates/*file controllers.Assets.at(path="/public/templates", file)
GET /images/*file controllers.Assets.at(path="/public/images", file)
#this line fails
GET /* controllers.Assets.at(path="/public", file="index.html")
It's not possible to omit usage of matching elements but you can route a client via controller. The route definition looks like this:
GET /*path controllers.Application.matchAll(path)
And the corresponding controller can be implemented as follows:
public class Application extends Controller {
public static Result matchAll(String path) {
return redirect(controllers.routes.Assets.at("index.html"));
}
}
Update
If you don't want to redirect a client you can return a static resource as a stream. In this case a response MIME type is required.
public class Application extends Controller {
public static Result matchAll(String path) {
return ok(Application.class.getResourceAsStream("/public/index.html")).as("text/html");
}
}
For this task you can use onHandlerNotFound in Global class which will render some page without redirect:
import play.*;
import play.mvc.*;
import play.mvc.Http.*;
import play.libs.F.*;
import static play.mvc.Results.*;
public class Global extends GlobalSettings {
public Promise<Result> onHandlerNotFound(RequestHeader request) {
return Promise.<Result>pure(notFound(
views.html.notFoundPage.render(request.uri())
));
}
}
Answer for scala developers using playframework :)
Similar to above one about creating controller which will accept parameters and then omit them.
Example routing:
GET / controllers.Assets.at(path="/public", file="index.html")
GET /*ignoredPath ui.controller.AssetsWithIgnoredWildcard.at(path="/public", file="index.html", ignoredPath: String)
controller with assets injected by framework:
class AssetsWithIgnoredWildcard #Inject() (assets: Assets) {
def at(
path: String,
file: String,
wildcardValueToIgnore: String,
aggressiveCaching: Boolean = false): Action[AnyContent] = {
assets.at(path, file, aggressiveCaching)
}
}

Resources