Runtime value in forRoot of Angular Module - javascript

In my angular app there is this module called Ngx-Stripe
I have defined it as documentation like following:
NgxStripeModule.forRoot('***your-stripe-publishable key***');
But the problem is I don't get this key on app bootstrap, I am not supposed to hardcode it in angular app.module or global like in index.html when I am using stripe withput any angular library.
I am getting this key on the api call after user proceeds to payment page. How can I define this key in this scenario ?

I wish it'd be straightforward, but the only way I was able to achieve it was something like:
index.html (alternatively webpack-injected script), has to be placed before Angular's sources:
<script>
var STRIPE_KEY = 'paste it here';
</script>
app.module.ts:
declare var STRIPE_KEY;
// ...
NgxStripeModule.forRoot(STRIPE_KEY);
The problem here is .forRoot() has to be statically-analyzed by Angular AoT compiler, so it can't accept what you want it to accept... How about setting the key after you got it via StripeService.changeKey(key: string) method?

Simply import StripeService from ngx-stripe and call changeKey on that service once you have your key.

For lazy loading your Stripe config key you can create your own instance of StripeService using StripeFactory that is available from ngx-stripe.
Check the documentation here for a full explanation:
https://richnologies.gitbook.io/ngx-stripe/core-concepts/service-factory

Related

Access javascript variable in component in Angular 5

I have a js file in my Angular application, data.js . This js file has some variables declared in it, something like below.
var data = 'test'
Now I have to access these variables and their values in my component (app.component.ts).
I read some where that declaring them as exports make them into modules and those can be accessed anywhere, But I'm not sure how this can be done.
This is the structure of my application. I have data.js in assets->js folder.I need to modify the variable value in app.component.ts.
I'm very new to Angular. Is this even possible?
With the file in your assets, I am guessing you are declaring it on the window. You will need the include the script in your index.html, and then access it on the window within your component via window.data. This is not really the recommended way of doing this unless your use case dictates it. The module approach you mentioned is preferred.
Next to your app.component.ts, create a file called data.ts, with:
export let data: string = 'data';
In your app.component.ts, import it using:
import { data } from './data.ts';
If you plan to not mutate that data, consider using the const keyword instead (in data.ts).
Directory structure
/app.component.ts
/data.ts
/...
Edit: Show Global Approach
You will need to include your script outside of the context of the Angular application. If you bootstrapped your application using the Angular CLI, you can add a reference to it in the cli configuration file. See this documentation on the topic.
That file will be included and will be available for access within your component on the window. The tricky part comes with typing and the Window. And example may look like this.
class AppComponent extends Component {
private data: string;
constructor() {
// Explicitly cast window as an any type. Would be better to type this, but this should work for you.
this.data = (<any>window).data;
}
}
(referrring to https://stackoverflow.com/a/42682160)
first you have to include the script into your src/index.html like
< script src="/assets/js/data.js">< /script>
important is that the above statement is placed before your angular root component tags
(< root-component>< /root-component> or < ion-app>< /ion-app> or something like that)
then you can simply write (for example inside app.component.ts ngOnInit function)
let varFromJsFile = window["data"] // varFromJsFile = 'test'
You want the variable to be a member of a Component class, not just a variable declared anywhere within a module.
If this doesn't make sense right away, you need to look more carefully at some basic Angular code samples.
Also, as long as you're using Angular and therefore TypeScript, it's better the declare variables using let or const.

Global Variable in Javascript for Laravel Routes - Is this a good idea?

I've created some code using a View Composer where I am passing my Route Collection through to the front end on all views, so I can access all of my laravel routes in Vuejs via the route named associated with them.
For example, to upload an image using a vue component, instead of passing my upload route into the Vue Component, it is listed as a part of a global variable:
var uploadRoute = _.find(globalRoutes, function(route) { return route.name == 'route-name.image.upload' });
$.post(uploadRoute, data) ... etc
My question is...is this sensible? I'm publically publishing my entire app's routes.
Thanks
I think your hunch about exposing your entire apps routes is legit. IMO you should explicitly pick out the routes that you need. So in thise case, you should only expose route-name.image.upload. You could create a tiny helper function to look up routes and output them along with the URL as JSON.
function json_routes(array $routes)
{
$return = [];
foreach($routes as $route)
{
$return[$route] = route($route);
}
return new \Illuminate\Support\HtmlString(json_encode($return));
}
And the, in your main view:
var routes = {{ json_routes(["route-name.image.upload"]) }};
Getting a route is simple:
routes['route-name.image.upload'];
This is the most basic exaple I can think of. You can optimize it quite a bit. Just some ideas:
Place the routes in a central place, fx. a config element: json_routes(config('app.json_routes'))
Build a command that generates a static .json file so that you don't iterate through the routes on each page load. Remember to re-generate when you add more routes.
Create a function instead of an object to get the route. That allows you to build in logic and gives a more Laravel-like feel in your js: function route(path){ return window.routes.hasOwnProperty(path) ? window.routes[path] : null ;}
(Advanced) Re-write Laravels router logic and hook into the options array, allowing you to do something like Route::get('dashboard', '...', ['as'=>'dashboard', 'expose'=>true]);, then dynamically generate the before mentioned json-file on all routes with the expose option.

Is it possible to create multiple dataStore in angular-localForage?

Is it possible to have multiple dataStore in IndexedDB using angular-localForage?
I tried this:
var $tblStage = $localForage.createInstance({
storeName : 'tblStage', // name of the table
});
but it triggered an error which says:
Error: A localForage instance with the name dbName is already defined.
I read this Question before but, is the only way is working with Raw IndexedDB? Or I missed something in my code? Any Idea?
Yes, only configure when you use.
https://github.com/mozilla/localForage#configuration
But no its possible two instance at same db.
If you intend to use the directive, local-forage, you'll have to copy and configure it.
Just like this https://github.com/ocombe/angular-localForage/blob/master/src/angular-localForage.js#L51, for change the provide,
only change defaultConfig at #L20, and name of angular module directive #L465.
And give more information but the reputation is very low and this leaves hook and my English so bad.

PapaParse with Angular JS

Liked the nice CSV parser & unparser of PapaParse. Can any one help me to get this combine with Angular JS.
I like to make PapaParse work in Angular Way. Trying for a solution.
I actually didn't do anything fancy to load it. Just add it to html file and to my lib folder. In my case: /lib/papaparse.min.js
and to index.html. As usual script:
<script src="lib/papaparse.min.js"></script>
then I just used it in my Controller:
Papa.parse(data, {
complete: function(results) {
console.log("Finished:", results.data);
}
});
You can use value to provide self contained third party libraries.
angular.module('your.app')
.value('yourLib', yourLib);
Then in your controller, or service, you would bring it in the normal way using DI
angular.module('your.app')
.controller('YourController', YourController);
YourController.$inject = ['yourLib'];
function YourController(yourLib) {
//. . .
}
If the third party line is a constructor function, requires it be newed, you may want to create a factory or a provider that has a method that accepts the passes params to the constructor returns a new instance.
Edit
After looking at PapaParse, you would want to register it with the angular injector using value.
just use a front-end modularization tool like requirejs to load papaParser in the context and call the api in any of your controller or service.
Just inject the script url in your index.html & then in your controller, access it as - var Papa = window.Papa;. That's it! You are ready for further actions!

Play 2.x: How to use two jsRoutes files in one scala template

I'm using jsRoutes in my Play 2.1.x app. Part of my routes file looks the following way:
GET /assets/template/js/routes/admin.js controllers.Admin.jsRoutes
GET /assets/template/js/routes/salonManagement.js controllers.SalonManagement.jsRoutes
And I would like to use both references in my scala template (that is by design, one controller contains necessary api functions, the other one necessary form submission urls).
So in my scala template I have the following part:
<script type="text/javascript" src="#routes.Admin.jsRoutes()"></script>
<script type="text/javascript" src="#routes.SalonManagement.jsRoutes()"></script>
Unfortunately, each generated javascript file starts with var jsRoutes = {};. Therefore, #routes.SalonManagement.jsRoutes() overrides properties of #routes.Admin.jsRoutes() and I can use only the last jsRoutes object.
Now, I know only one workaround. After each jsRoutes declaration I can insert a script that copies old jsRoutes object to a temporary object and then extends new jsRoutes with itself. But that doesn't look like the right way to go.
Isn't there any better way?
There's nothing special about the "jsRoutes" name. You can keep the same method name for consistency among the various controllers, but just pass a different name to the Routes.javascriptRouter method.
Put this in your template. I put it in a main template that wraps the other pages.
<script src="#controllers.routes.Application.jsRoutes()" type="text/javascript"></script>
and put this in your routes file
#jsroutes for ajax calls
GET /assets/js/routes controllers.Application.jsRoutes()
And then in your Application controller, refer to whatever method in whatever controller you want by implementing this method
public Result jsRoutes()
{
response().setContentType("text/javascript");
return ok(Routes.javascriptRouter("jsRoutes",
routes.javascript.Signup.forgotPassword(),
routes.javascript.Customers.findByName(),
routes.javascript.Customers.findByNumber()
));
}
These correspond with routes like
GET /customerfind/:name controllers.Customers.findByName(name: String)
Note there is no need to include parameters for the calls configured in the jsroutes method. Keeping all of this in one place, the Application controller, seems reasonable as long as it refers to methods implemented in their appropriate controller. Like in this example, a find on customer is in the Customers controller. Also, is kindof nice just having to check the one controller (Application) to see all the methods available through javascript routes for ajax calls.

Categories