How to make global variable reactive in Svelte? - javascript

The following code does not run when I update the window.test variable, I do not have any log displaying on my console. I thought that test() would be run. Can't we make global variable reactive using svelte ?
$: window.test && test();
function test() {
console.log('success');
}

No, we can't make global (or imported) variables reactive.
Svelte's reactivity for assignments is restricted to local variables inside *.svelte files.
The recommended method to enable reactivity in other places is by creating stores, either by using svelte/store directly or by using objects that fulfill the Store contract.

Related

How to access class attributes and functions within modules properly

I'm writing classes in ES6 modules using object literals and I want to set object attributes within a function. Now I know modules are executed in strict mode by default which makes usage of this safe or at least safer, but I'm not sure whether foo() modifies the object I'm accessing in the 'parent' script file or just the local object existing only in Controller.mjs. Do both function calls have the same effect?
//Controller.mjs
const Controller = {
someAttr1: [],
someAttr2: true,
foo: function () {
this.someAttr1.push("some value");
Controller.someAttr1.push("some value");
}
};
//export Controller's interface...
//SomeOtherFile.mjs
import { Controller } from 'Controller.mjs'
Controller.foo();
the object I'm accessing in the 'parent' script file or just the local object existing only in Controller.mjs
There is only a single object in your code. The import declaration really does nothing but create an alias for the const Controller variable in the imported module. There is no second object getting instantiated.
In general, for using this vs Controller to refer to the object, see Javascript: Object Literal reference in own key's function instead of 'this'. It doesn't matter whether the code is spread across modules or not for that.

Global variable in AngularJS (good practice)

I'm looking for a pattern in order to have globals constant in my application. But not with a controller or a factory. (so not with app.constant() too)
I just want to set a variable but I didn't find something good.
I wanted to set this var in my rootScoop but without success.
with something like
myApp.run(function($rootScoop){
$rootScoop.global = {};
});
When I use that code, an arror occurs for nothing (transtateFilterProvider). When I delete this code, the translateService works,
I MUST have access in all html view, I don't want to always use a controller (useless in this case), I just want to set a global variable in rootScoop.
Thank you.
You are getting an error because it is :
$rootScope
And not
$rootScoop
Anyway, correct way to do this is to add a constant module to your app like :
angular.module('yourapp', []).constant('Constants', {
foo: 'bar'
});
But you'll have to call Constants in controllers.
If you use $rootScope, remember you will need to call $root.global in templates.

Why use AngularJs .constant() if I can declare JS const?

I'm working on an AngularJS project where there is a .constant() provider to declare some basic information used across the whole project. For example, a definition of cookie name. Ex.:
.constant('appConst', {
cookie: 'CookieName',
...
});
But the same thing can be done by declaring a const, ex.:
const appConst = {
cookie: 'CookieName',
...
}
So, what is the advatage of using the .constant provider instead of just declaring a const? I know one of the reasons is because we don't expect the value to change. But isn't this the same objective of a const?
The new const keyword only makes it so you cannot reassign the variable, it doesn't make any object you initially assign to it immutable. So in your example with:
const appConst = {
cookie: 'CookieName',
...
}
You would still be able to change the value of cookie. You just wouldn't be allowed to do something like this:
appConst = { // My new object };
The values in the angular .constant() can also still be changed, so they're not constant in the common use of the word "constant". At least not when you use it like this:
.constant('appConst', {
cookie: 'CookieName',
...
});
So if you for instance do like this and change the value within a controller
app.controller('myController', function(appConst){
appConst.cookie = 'NewCookieName';
})
the change would be reflected anywhere you inject appConst after this controller was constructed.
You can't "reassign" appConst in this case though, that action would just be ignored, so it is constant in that sense.
1- const is new in ES6, so you may need to transpiler your code for supporting old browsers.
2- const is block-scoped, so within a scenario, you define a constant in A.js, will be not able to use it at B.js unless you're using a module bundler, so we went back to the topic 1-.
The main purpose of AngularJS having this native is to able you to share it between controllers, services, and directives, using its dependency injection system.

What is the proper way to store persistent variables in Ember RESTAdapter

Sometimes you want a variable that is persistent as long as the page is not reloaded. Since a lot of the Ember convention is extending objects, I'm not sure where to put private variables so that they are accessible from public functions.
It seems obvious to just put it in the extend()ed object, but then the variable isn't reachable from within a function in that same object, probably because Ember doesn't bind() the parent object to the function.
Here's an example of how I store an array so that I can deduct if my RESTAdapter should reload a record that has been requested before:
shouldReloadRecord: function(store, snapArray) {
window.recordHashStore = window.recordHashStore || [];
let recordHash = `${snapArray.modelName}/${snapArray.id}?include=${snapArray.include}`;
if (!~window.recordHashStore.indexOf(recordHash)) {
window.recordHashStore.push(recordHash);
console.log('Reloading', snapArray.type);
return true;
}
else {
console.log('NOT reloading', snapArray.type);
return false;
}
}
the relevant code here is window.recordHashStore = window.recordHashStore || []. This does exactly what I want, but it doesn't look very Ember'y. Also it's not nice to use the window global scope. Where can I store private variables for the duration of the app in the browser, so that it's available and not overwritten on transitions?
This sounds like a good use case for an Ember.Service. A Service is essentially a singleton, but it isn't exposed in your window/global scope. It also isn't affected by route transitions (unless you have code that manipulates a service on route transition).
You can inject your service into your RESTAdapter, and store the state in the service.

Using controllerAs syntax in Angular, how can I watch a variable?

With standard controller syntax in AngularJS, you can watch a variable like:
$scope.$watch(somethingToWatch, function() { alert('It changed!'); });
Using the controllerAs syntax, I want to react to this change in an active controller. What's the easiest way to do this?
More detail, if it helps. I have one controller in a side pane that controls the context of the application (user selection, start time, end time, etc.). So, if the user changes to a different context, the main view should react and update. I'm storing the context values in a factory and each controller is injecting that factory.
You can always use a watcher evaluator function, especially helpful to watch something on the controller instance or any object. You can actually return any variable for that matter.
var vm = this;
//Where vm is the cached controller instance.
$scope.$watch(function(){
return vm.propToWatch;
}, function() {
//Do something
}, true);//<-- turn on this if needed for deep watch
And there are also ways to use bound function to bind the this context.
$scope.$watch(angular.bind(this, function(){
return this.propToWatch;
//For a variable just return the variable here
}), listenerFn);
or even ES5 function.bind:
$scope.$watch((function(){
return this.propToWatch;
}).bind(this), listenerFn);
If you are in typescript world it gets more shorter.
$scope.$watch(()=> this.propToWatch, listenerFn);
Eventhough you can watch on the controller alias inside the controller ($scope.watch('ctrlAs.someProp'), it opens up couple of problems:
It predicts (or in other words pre-determines) the alias used for the controller in the view/route/directive/modal or anywhere the controller is used. It destroys the purpose of using controllerAs:'anyVMAlias' which is an important factor in readability too. It is easy to make typo and mistakes and maintenance headache too since using the controller you would need to know what name is defined inside the implementation.
When you unit test the controller (just the controller), you need to again test with the exact same alias defined inside the controller (Which can probably arguably an extra step if you are writing TDD), ideally should not need to when you test a controller.
Using a watcher providing watcher function against string always reduced some steps the angular $parse (which watch uses to create expression) internally takes to convert the string expression to watch function. It can be seen in the switch-case of the $parse implementation

Categories

Resources