Creating global variables using JavaScript for QML - javascript

I'm having an issue with QML/JS integration.
I have a javascript list variable stored in a .js file. I want to write to this variable from one QML file, and read it from another QML file. I cannot seem to find a solution to this. I've over-simplified my actual code to make it comprehensible!
// writeValue.QML
import "../javascript/storedValue.js" as StoredValue
...
MouseArea{
onClicked{
StoredValue.value.push(1)
}
}
// readValue.QML
import "../javascript/storedValue.js" as StoredValue
...
Text{
text : StoredValue.value
}
//storedValue.js
var value = []
I have tried using '.pragma library' and not using it, to no avail.
What happens is the writeValue.QML writes successfully, so [1, 1, ,1, ...]. Whereas readValue.QML just finds an empty list, [].

Just put .pragma library at the beginning of the JS file. In this way, there will be only one instance imported by QML components.
Remember however that no update signal is issued when a var property changes. If you want to have global var with update support, you should export a custom QObject via setContextProperty() on the C++ side.

Related

Functions included from the prototype in a javascript class are not seen in the editor's autocomplete

I have the following problem, I have created a library. which its methodos
they are in separate files writeLog.js in a folder called ./lib.
and I have an index.js file that explores that folder and extracts the function
and puts the same name as the file as the function name.
example:
writeLog.js
and then I can use
let jsPackTools require('./index');
let utils = new jsPackTools();
utils.writeLog('test');
The way I use to add the methods to the classes is through the prototype.
the folder is scanned with readdirSync () and then I take the file name to
place it inside a require ().
the code is the following:
fs.readdirSync(__dirname+'/lib').forEach(modules => {
let module = modules.split('.').shift();
jsPackTools.prototype[module] =require(\`${__dirname}/lib/${module}\`);
});
Everything works perfectly fine, the problem is that when I want to access my methods through the autocomplete of any code editor. Methods they seem to be not accessible. however everything works perfectly, I can do use of functions.
    
The problem is that I have to know each method that I am going to use and it cannot be visualized in the completed auto of any editor.
I have tried with:
const writeLog = require('./lib/writeLog');
class jsPackTools {
get writeLog() { return writeLog.bind(this) }
}
This allows indexing perfectly. however, I don't logo do it dynamically.
The idea is that the class does not know what its methods are until the ./lib folder is scanned and all methods are extracted. This way you can add functions inderteminately and when you use them you can see.
    
I do not want to use transpilators, I thought of using a d.ts but it is necessary to use typeScript but the intention is to create this library without dependencies or the least possible.

How to access c# variables from a JavaScript file?

I have a C# file that pulls various config settings from different config files. A JavaScript application I'm writing needs some of those settings to run. I'm having trouble bringing the C# variables into the js file. Not sure what is the best approach. They need to end up as a JS object on the page. Would adding them to a JSon object in the C# file & calling that from the JS file work? Not even sure how to do that to be honest. Any help appreciated.
You can just declare a global variable in one of your root pages (say, _layout.cshtml):
<script>
var settings = {
foo: #(IsFoo ? "true", "false"),
bar: #SomeNumber,
baz: "#ImportantString"
}
</script>
Or, if you're writing a Web API, you can just add a /settings endpoint you can query like so (Assuming you're using jQuery):
$.get("/settings", response => {
// Store the `response` in a global variable.
});
If it's an independent javascript project and .net is more of an API, you need to make an API call which will send you those config settings.
If your javascript is part of .net MVC application, i.e., you are adding your javascript through an tag at then end of a .cshtml/.aspx file, you can easily pass it through a global variable, but even then the C# code need to pass those values through Modal to the .cshtml/aspx file.
what you can do is:
var pageConfig = pageConfig || {};
pageconfig.settings = #Html.Raw(Model.Settings); // This model object is part of the C# code and my assumption is that Settings will have array of configurations.
This can also be done globally, depending upon how the C# code is written.
Assuming that when you say 'various config settings' you're referring to .NET's ApplicationSettings (defined in Visual Studio's Properties > Settings), we've done something similar, in a generic manner, as follows:
public void WriteSettings(TextWriter writer)
{
// Declare the nameSpace for the DLL you want to pull settings from
var nameSpace = "foo.Bar"
ApplicationSettingsBase properties = (System.Configuration.ApplicationSettingsBase)Activator.CreateInstance(nameSpace, string.Format("{0}.Properties.Settings", nameSpace)).Unwrap();
foreach (SettingsProperty property in properties.Properties)
{
writer.Write(string.Format("{0}=\"{1}\", property.Name, properties[property.Name]);
}
}
I've ignored a few issues in your case:
I've not bothered trying to deal with non-strings; consider looking at property.PropertyType and casting your values appropriately
I've wrapped this in a function that accepts a TextWriter; you can pass this method Response.Output

Unable to refer javascript array from another javascript file

I am trying to create a chart using highcharts in which i am not able to fetch data which i store in another js file.
My main.js file has all the code for creating chart. It has the section of series.
series: [{
name: 'Desktops',
data: '/data/desktop.js',
tooltip: {
valueDecimals: 2
}
}]
Here i want to refer data from another js file. The name of file is desktop.js and it has just the below array
var desktopData = [[1475272800000, 117759], [1475359200000, 106147], [1475445600000, 147747], [1475532000000, 302031], [1475618400000, 520539], [1475704800000, 245353], [1475791200000, 180376], [1475877600000, 78819], [1475964000000, 90466], [1476050400000, 257822], [1476136800000, 284465], [1476223200000, 242898], [1476309600000, 297186], [1476396000000, 268069], [1476482400000, 183149], [1476568800000, 410442], [1476655200000, 1117798], [1476741600000, 1274668], [1476828000000, 1331799], [1476914400000, 1230213], [1477000800000, 888251], [1477087200000, 572050], [1477173600000, 931144], [1477260000000, 1556641], [1477346400000, 1526736], [1477432800000, 1310133], [1477519200000, 1207422], [1477605600000, 785556], [1477692000000, 487264], [1477778400000, 787714], [1477868400000, 942663]];
How can i refer array defined in another file?
Do you use any type of the framework? To load JS file in another file, you need to require it somehow, either by using AMD, ES imports or any other way (be it synchronous or asynchronous).
If you are just adding the files to the HTML (using script tags), then the only thing you have to do is to make sure that the files are loaded (DOMContentLoaded event) and then, you have to attach the data to a global scope.
Global scope in the browsers is called a window and every time when you use variable that was not declared in your scope by var it means that the JS is searching for it in the global scope. In order to assign something to a global scope you can just omit var or explicitely assign it like this:
window.desktopData = [];
// And then in another file, assuming that the data is ready
var myData = window.desktopData
Please also remember that including files in <script> tags usually means that they will block your browser and the order of the files matters (at least when you want to rely on the fact of one file already loaded before another file). I'd suggest using some kind of import system then:
http://requirejs.org/docs/whyamd.html

Appcelerator titanium - passing js variables

I am new to JS and Appcelerator titanium. I am trying to implement the MVC model to my app, but I have a problem accessing the data in the model:
in the model.js:
var my_val;
then in file1.js, I modified the value of my_val:
Ti.include("model.js");
my_val=5;
then in another file file2.js:
Ti.include("model.js");
T.API.info(my_val); // the value I always get is "undefined"
why is file2.js not detecting the change file1.js has done to my_val? Is there anyway to make it work?
take a look at my blog posting regarding this particular problem.
blog.clearlyinnovative.com
you want to include both files in your app.js and add the variable to your namespace; this is cleaner and doesn't pollute the global scope.
var myApp = {};
Ti.include("model.js");
Ti.include("file2.js");
in model.js do something like this
var myApp.model = {};
myApp.model.my_val = 100;
in file2.js do something like this; no need to incude model.js again, the value was set in your own namespace and is clearly defined
Ti.API.info(myApp.model.my_val);
If you want to get this functionality done use Titanium Properties so that you can get/set your variable as per requirement.Do something like this in your app.js
// initialize your variable, you can update it as well with your custom value
Titanium.App.Properties.setInt('my_value', 0);
You can get this value any where you want like this:
var myValue = Titanium.App.Properties.getInt('my_value');
This is because what the statement
Ti.include('model.js');
does is to just sort of 'copy-paste' the code in your 'model.js' file into the other two files. All the variables in 'model.js' will be available to the file in which you included 'model.js'. But this only means that a copy of the variable my_val is made available to 'file2.js' not a variable that is common to all files that have the Ti.include('model.js') line!Including a file in another is pretty much the same as typing out the lines of the first file into the second but it in no way connects all files that include a common file!
So maybe instead of
Ti.include('model.js');
Ti.API.info(my_val);
you can this try this seeing as you have already included 'model.js' in 'file1.js??'
Ti.include('file1.js');
Ti.API.info(my_val);
OR you can always go with Muhammad Zeeshan's advice and check out Ti.App.Properties. Good Luck! :)

send data to JS file without using global variables

I need to send data in a HTML page to a script file that is loaded in that page. The simplest way i can think of is to use a global variable which is defined in the page and accessed in the script file.
We all know global state is bad, so i started thinking about the options available for passing data from HTML page to script file without using global state. I cant find (or think of) any.
I am curious whether this is possible. Any ideas?
It really depends what you're doing. In general, I wouldn't advise this methodology, but it's something to consider depending on your circumstances. For the sake of this example, I'll assume you're using jQuery (if not, replace the document.ready with whatever you want to use for onDOMReadyStateChange monitoring).
In the HTML:
<script type='text/json-data' id='some_data_set'>
{ 'foo': 'bar', 'baz': 1 }
</script>
In the JavaScript:
$(function() {
var myData = JSON.parse($('script#some_data_set').html());
// YOUR CODE GOES HERE
});
Nope. All the javascript scope starts from a global level, therefore you must have at least one global reference to your data.
Let's say you wanted to store a list of products and events:
var myGlobalData = { "products":<products>, "events":<events> };
Where <products> and <events> are two different data blocks.
If you're paranoid on global objects, you can simply delete the reference point (thus it's contents) after you finished using it, as follows:
delete window.myGlobalData;
One option is to scope your data. For example, in JS file you can define an object like:
var processor = {
function setData(o) { // do stuff
}
};
Then in your HTML you know that the data is scoped to the processor. So you can do something like:
processor.setData({someData});

Categories