I would like to create a global function called "translate". As i know, i can define global variables and their values in the app.module.ts file. So i tried following code:
export function translate(string) {
// i am not sure if it would make a difference if i would use var
let ts = new TranslateService();
return ts.get(string).subscribe(res=>{
return res;
});
}
So maybe i try to use the wrong class, maybe the mistake is somewhere else. I use the ngx-translate Module (and it works great). Instead of always declaring to use the "TranslateService" (in every class where a translation is needed), i want to have a global function, where i can access the translations via only a function (i do not want to call another class...). You can see the code that i do like to use in the global function at the very end of the link (ngx-translate)
Thanks in advance.
global means for me, that something is accessible everywhere in the project.
I think thats a very bad idea, even if you get it to work somehow by some messy hack thats not the way this is intended to work.
TranslateService is already a service you can inject in every class you need it. And injecting a service using Angulars dependency injection is the intended way to use it. If you are afraid that there will be multiple translate services in the end - don't worry, Angulars dependency injection system takes care of that.
I guess you want to do this because you always have to write public translate: TranslateService in your constructor. But if you export a function in your app.module you have to import it again in your class, so you will have to write import { translate } from 'path/to/app.module/translate'; instead every time.
Related
So, I am working on an MVVM-based core SDK for use any time I am developing some Google Apps Script based software, called OpenSourceSDK. It contain core business logic, including base classes to extend. For example, the file Models/BaseModel.gs in it is defined to be:
class BaseModel {
static FromObject(obj) {
let model = new this()
return model.unmarshal(obj)
}
/**
* Creates a deep-copy of this, as plain Object
*/
marshal() {
return JSON.parse(JSON.stringify(this));
}
/**
* Writes the target object into this and returns this
* #param {*} obj
*/
unmarshal(obj) {
return Object.assign(this, obj);
}
}
I follow the instructions to create this library, and make sure to import it into the project that's using it. When I attempt to use it, things go sideways: I am able to access the functions, but not the classes nor the constants!! I start typing in OpenSourceSDK.BaseModel, and IntelliSense is like "idk what to do". I sanity test via Logger.log(typeof OpenSourceSDK.BaseModel), only to get undefined.
This is unacceptable.
What is the most efficient way to make sure these classes (and constants) are shared from that library?
NOTE: I do not accept the following "solutions":
factory method per class. Why not? Because:
maintenance nightmare. Imagine making any change to the constructor signature of the class. You'd have to update the factory function on every change!
extra boilerplate that is wrapper around something that is so simple.
what happen if we want to extend a base class coming from the library?
going all function-based. That defeats the whole purpose of this project. There's a reason I am doing this MVVM, and hence OOP, style.
In ES6 let, const, and class do not add themselves to the global variable (unlike var and function).
My favorite way of exporting them on Apps Script is to assign all exported objects to globalThis:
class BaseModel { /* [...] */ }
class AnotherType { /* [...] */ }
const ExampleConstant = 420
Object.assign(globalThis, {
BaseModel,
AnotherType,
ExampleConstant,
})
This allows you to choose what to "export" and follows a nice enough syntax.
Update
You can also mimic the individual export syntax with the following function:
function export_(exported) {
const { name } = exported
if (!name)
throw new Error(`To export a function or a class, it needs to have a name.`)
if (name in globalThis)
throw new Error(`A feature with the same name already exists on globalThis.`)
globalThis[name] = exported
return exported
}
And you use it like this:
export_ (class Example {
// [...]
})
Unfortunately the final underscore is necessary to not clash with the keyword and the parenthesis are not my cup of tea (specially the one at the end). But I agree that this would be more maintainable as you don't need to manually update the list.
References
globalThis (MDN)
Object.assign() (MDN)
I was able to get it resolved, but the solution is...hacky.
So, apparently, Google Apps Script exports only what is in globalThis of a project: just the functions and variables. No classes, no constants, ...
Probably has a lot to do with how ES6 works, with its globalThis behavior. One can see that in action, by creating a dummy function, a dummy variable, and a dummy class in their local developer console:
function aFunction() { return 42; }
class AClass {}
var a = 41;
When they log globalThis, they'll find some massive object with a, aFunction in it, but no class:
Also, it turns out that globalThis is immutable, so you can't hack the class in via some IIFE...
The only recourse is to go prepend var [ClassName] = in front of every class that is to be made public. That would assign the [ClassName] to a publicly exposed var.
I can't wait til Google Apps Script comes up with a better way to expose classes!!
I know very little about Flash, but I need to be able to call a JS function from inside a ActionScript file.
When I enter the line:
ExternalInterface.call("alert", "test");
I get the error:
There is no method with the name 'ExternalInterface'.
In the tutorials it seems I have to include the namespace:
import flash.external.ExternalInterface;
but I don't know where to put that?
I place it outside the class that extends a mediaclip and it does nothing.
How do I include that reference so that the ExternalInterface method is recognized?
What's odd is that intellisense works and allows me to type it in and gives me the overloaded methods, so it knows what I'm trying to say, it just doesn't work when I try to compile it.
You could also try access the class doing this:
flash.external.ExternalInterface.call("alert", "test");
That way you don't have to import the package with the class.
I've created a library class file in my CakePHP 2.0 app. It's a single PHP class called emailManager Which exists within a folder emailManager within CakePHP's libaray folder. I would love to know what is the simplest way to reference the database from this library class.
I would love to be able to do something like $this->AppModel->query("SELECT * FROM some_table_in_my_db"), that way I do not have to track DB configurations in separate places, but I'm not sure how to achieve this.
Also, I feel it is important to mention that the tables I am working with do not adhere to CakePHP table naming convention. They predate our use of CakePHP and so I cannot change my tables to fit CakePHP's model format. this is why I want generic database access via something like query
EDIT: I have constructed a temporary solution, but I know a better one is possible.
I have a model in my cake app called MySimpleConstuct and then in the library file I include the MySimpleConstruct Model as followed:
// import this model
$this->GivenModel = ClassRegistry::init('MySimpleConstruct');
$this->GivenModel = new MySimpleConstruct();
// Then it is possible to do as followed:
$table_data = $this->GivenModel->query('SELECT * FROM like_some_table_dude' WHERE 1);
This is not ideal so I still searching for a better solution.
Any help would be greatly appreciated.
#John Galt, I suppose it's not an exact duplicate but it is very similar and the resolution does appear to apply to your situation very directly.
The other technique you could consider using would be to instantiate the Library in the controller and than give it a reference of the model.
class TestController extends AppController {
function index(){
App::uses('TheLibrary', 'Lib');
$obj = new TheLibrary();
$obj->GivenModel = &$this->GivenModel;
}
}
-EDIT-
And then within the library you've written do something like this.
class TheLibrary {
var $GivenModel = null;
function some_query(){
return $this->GivenModel->query('SELECT * FROM like_some_table_dude WHERE 1');
}
}
The first code snippet is of the Controller instantiating your library and then giving the library a reference to the Model as the property GivenModel. The "&" symbol makes the assignment a reference (see How does the '&' symbol in PHP affect the outcome?). The second code snippet is of a sample of how the library would use that property.
I do understand that you are trying to use a model from the library and that is what the solution you have in your edit and my proposed solution both do. However I will note again that this is not proper MVC convention and you should reconsider how you are using Libraries.
I have created a custom event that I want to use to pass a string between two modules. The event looks like this:
package com.mypackage.events
{
import flash.events.Event;
public class ThumbDeleteEvent extends Event
{
public static const THUMBS_DELETED:String = "thumbsDeleted";
public var files:String;
public function ThumbDeleteEvent(type:String, files:String)
{
super(type);
this.files = files;
}
// Override the inherited clone() method.
override public function clone():Event {
return new ThumbDeleteEvent(type, files);
}
}
}
In one module I dispatch the event like so:
parentApplication.dispatchEvent(new ThumbDeleteEvent("parentApplication.thumbsDeleted", files));
and in another module I listen for the event like so:
public function init():void {
parentApplication.addEventListener("parentApplication.thumbsDeleted", onThumbsDelete);
}
if I use ThumbsDeleteEvent as the type passed in to the listener function like this:
public function onThumbsDelete(evt:ThumbDeleteEvent):void{
trace("thumb delete event for thumbs: "+evt.files);
}
I get the following error:
TypeError: Error #1034: Type Coercion failed: cannot convert com.mypackage.events::ThumbDeleteEvent#26748a31 to com.mypackage.events.ThumbDeleteEvent.
if I just use Event as the type passed in to the listener function like this:
public function onThumbsDelete(evt:ThumbDeleteEvent):void{
if(evt is ThumbDeleteEvent){
trace("thumb delete event for thumbs: "+(evt as ThumbDeleteEvent).files);
}else{
var type:XML = describeType(evt);
trace(type.toXMLString());
}
}
It works but does not think it is a ThumbDeleteEvent type class (it hits the else statement) the xml output of describe type says its type is:
type name="com.mypackage.events::ThumbDeleteEvent"
What is going on here? If I put a breakpoint in the debugger it says the event is a ThumbDeleteEvent and I can see the files parameter and its right???
The issue here is that one swf has their definition of that class, and then the other swf has its own version of that exact same class. When trying to cast between them flash does a bytecode-check to see if the definitions are the same, and if you ever changed something in that as file without updating both with the exact same info you will run into this issue. That is, compile both swf-files, then change a space in the as-file, and compile only one swf file.
Urgh it's coming back to me, all those issues with shared code between different modules. I always just slug my way through these errors until I get it to work and can never really remember what it is since it can be so many issues.
Make sure both compiled swf-files have up-to-date-versions of the file.
Make sure both swf-files have same linkage-nesting to the code-file.
If that doesn't work [can't really remember since this issue is kind of like solve-once and copy to every other project].
See in which order things are added to ApplicationDomain and make sure nothing else has their own out-of-date-version of it through something imported in flash library
Move shared code into seperate code library linked in with "dynamic binding"
Try with sharing the Interface instead
Change how assets are loaded into the ApplicationDomain
Hopefully someone has more knowledge of this issue and can tell exactly what steps to use, but this is at least a starting point... I might have more time to research this and write a post about it sometime in the future later today.
Edit:
from another SO-thread Custom AS3 Class not Updating
This is the age old problem of what ultimately boils down to is the Verify Error. It happens when you embed "Class A" in one or more applications, modules, swfs, etc. Ultimately every output swf that uses "Class A" must be recompiled when "Class A" is changed. Otherwise you end up with a situation where 1 module has the newer implementation but others don't. This problem is compounded by the fact that the application domain is defined as a "first in wins" when it encounters a Class of the same name / package - meaning if the old one is referenced first, the newer one loaded later gets ignored.
The more permanent solution is to use class promotion to an RSL that ultimately allows the RSL to control the actual "Class A" reference in which it also implements an "IClassAImpl" interface that all modules use. This allows the compiler to cross link the reference with a signature it knows about without actually embedding the actual class itself.
As I've been working with AS I've developed a collection of utility functions. For example:
$ cat utils/curried.as
package utils {
public function curried(f:Function, ...boundArgs):Function {
function curriedHelper(...dynamicArgs):* {
return f.apply(null, boundArgs.concat(dynamicArgs));
}
return curriedHelper;
}
}
And I've found that, some times, I want to keep more than one public function in each file... But ActionScript restricts me to one public definition per file, if that file defines its self as being part of a package.
So, without creating a class with static methods, how could I get more than one public function in a single .as file?
simply put, you can't ... for a package level function declaration, you need one file per declared function ...
little side note: personally, i'd go Josh's way and stuff them into a class ... i think allowing function level declarations at all was simply to have a bit more backward compatibility to AS2 ... it's ok, for prototyping or things that'll never leave your hands ... but you imagine relying on 3-4 libraries, each exposing their functionality through package level functions? firstly, it completely spams your autocompletion (if your IDE offers one), and secondly, you always need to look at the imports to see which function comes from where ... the prefix you mentioned is actually of great advantage ... but ok, that's my opinion ...
greetz
back2dos