Native JS

Mit Native JS führen Sie JavaScript-Code innerhalb eines Ninox-Skripts aus und teilen Funktionen und Variablen mit ihm. So kann Native JS auf Ninox-Variablen zugreifen und sowohl lokale als auch globale Funktionen aufrufen.

Bild.png

Einschränkungen

Ändert man eine Ninox-Variable in Native JS, so wirkt sich das nicht auf die Ninox-Variable aus.

JavaScript wird ausschließlich lokal ausgeführt. JavaScript in Code einzufügen, der auf dem Server läuft, hat keine Wirkung. Ebenso hat es keine Wirkung, aus servergestütztem Code eine globale Funktion aufzurufen, die JavaScript enthält.

Welche Codes lokal und welche auf dem Server ausgeführt werden, sehen Sie hier:

Bild.png

Syntax

Ausführung

Um Ninox mitzuteilen, dass Sie zu JavaScript wechseln, müssen Sie den Code in #{ ... }# einschließen:

#{ alert("hello world") }#;

Denken Sie daran: Ninox ist eine vorkompilierte Sprache, die den Typ jeder Variablen und jeder Funktion im Voraus kennen muss. Dasselbe gilt für Native JS – Sie müssen den vom JavaScript-Code zurückgegebenen Typ angeben. Standardmäßig gibt Native JS Text zurück; Sie können aber den gewünschten Rückgabetyp angeben, indem Sie ihn ganz am Anfang des Codes mit der Schreibweise :[type] notieren:

Rückgabewert

#{:text return "hello world"}#;

Die möglichen Typen sind dieselben wie bei Funktionsaufrufen: text, number, date, datetime, time, timeinterval, appointment, boolean, html, color, icon, email, phone, location, file, user und any.

Array-Typen

Um ein Array zurückzugeben, verwenden Sie folgende Syntax:

#{:number(array) return [1,2,3] }#;

Datensatztypen

Um Datensätze zurückzugeben, verwenden Sie den Tabellennamen gefolgt von nid oder rid:

Verwenden Sie nid, müssen Sie ein Array von Textwerten mit dem vollständigen Datensatzbezeichner zurückgeben, also Tabellenbezeichner + Datensatznummer:

#{:nid(customer) return ['A1','A2','A3'] }#

Verwenden Sie rid, geben Sie die Datensatznummer zurück:

#{:rid(customer) return [1,2,3] }#

Bei zusammengesetzten Tabellennamen setzen Sie kein wie in Ninox, sondern schreiben einfach den vollständigen Namen der Tabelle:

#{:rid(my long name table) return [1,2,3] }#

Mit dieser Syntax liefert Native JS Variablen, die sich genauso verhalten wie Ninox-Code. Sie können also folgende Schreibweise verwenden, als handelte es sich um ein select:

(#{:rid(customer) return [1,2,3] }# order by 'Last Name').'First Name';

Bild.png

Datensatz ändern

Variablen vom Typ Datensatz werden im JSON-Format übergeben, mit einem Schlüssel-Wert-Paar für jedes Feld des Datensatzes.

var r := first(select Customer);
#{:text return r['First Name'] }#;

Der Inhalt der Variablen r sieht in JavaScript so aus:

{
 "Created on": 1648910817206,
 "Id": "A1",
 "Last modified": 1714817525840,
 "Modified by": "7zBqhAKXxfQAPmH7Y",
 "First Name": "Sofia",
 "Last Name": "Young",
 "Company": "Kollwitz GmbH",
 "Postal Code": "12345",
 "City": "New Jersey",
 "Address": "11,South Commerce Street",
 "Email": "sofi@kollwitz-gmbh.com",
 "Customer No": "K0001",
 "Title": "2",
 "Invoices": [
  1,
  16,
  17
 ],
 "Photo": "shutterstock_307218608.jpg",
 "Category": "1",
 "Position": "Marketing head",
 "Checked": true,
 "ID": "A1",
 "id": "A1"
}

Wichtig

Je nachdem, ob der Code in der Mac-Anwendung oder im Web ausgeführt wird, kann die ID unterschiedlich groß- und kleingeschrieben sein.
Um dem zu begegnen und Konflikte zwischen den Plattformen zu vermeiden, wird die ID in allen möglichen Schreibweisen wiederholt.

Ändert man den Datensatz in JavaScript, so wird er in Ninox nicht aktualisiert.

Asynchrone Ausführung

Manchmal ist es sinnvoll, die Ausführung von Ninox-Code mit JavaScript zu synchronisieren.
Verwendet man zum Beispiel einen Timer, so ist es wichtig, dass der Code erst dann endet, wenn der Timer abgelaufen ist.
Ohne diese Synchronisierung liefe der Code nach der JavaScript-Ausführung sofort weiter, was zu unerwartetem Verhalten führen kann.

Im ersten Fall wird der Wert „I don’t know“ sofort zurückgegeben, und die Funktion alert zeigt das Ergebnis an, bevor dem Benutzer die Frage überhaupt gestellt wurde.

var r:= #{:text
   setTimeout( () => {
      if (confirm("Are you ok ?"))
        return "of course";
      else
        return "Never !";
   }, 2000);
  return "I don't know";
}#;
alert( "Your answer is : "+r );

Bild.png

Wechselt man in den Modus callback, so läuft die Ninox-Funktion alert erst dann, wenn der JavaScript-Code die Callback-Funktion aufgerufen hat – also nachdem dem Benutzer die Frage gestellt wurde.

var r:= #{:text:callback
   setTimeout( () => {
      if (confirm("Are you ok ?"))
         callback( "of course" );
      else
        callback( "Never !" );
   }, 2000);
   return "I don't know";
}#;
alert( "Your answer is : "+r );

Bildschirmaufnahme 2025-03-03 um 11.46.26.gif

Funktionsaufruf

Aus JavaScript heraus lassen sich Ninox-Funktionen aufrufen. Die Prozedur kann lokal oder global sein; sie muss lediglich im Gültigkeitsbereich des JavaScript-Codes liegen.

function display( message : text ) do
    alert( message );
end;
#{ display('hello world') }#;

Bild.png

Um den Rückgabewert einer Funktion zu erhalten, müssen Sie wiederum den Callback-Modus verwenden (siehe oben: Asynchrone Ausführung):

function add( a : number, b : number ) do
    a + b;
end;

#{:number:callback
   add( 1, 2, (returnValue) => {
     callback( returnValue )
   })
}#;

Bild.png

Wenn Sie nach dem Aufruf der Prozedur nichts weiter verarbeiten müssen, können Sie die Callback-Funktion direkt als Parameter übergeben:

function add( a : number, b : number ) do
    a + b;
end;
#{:number:callback
   add( 1, 2, callback )
}#;

Bild.png

Datensätze und Funktionen bearbeiten

Wenn Sie eine Liste von Datensatz-IDs haben, können Sie eine Ninox-Funktion aufrufen, um jeden Datensatz einzeln zu ändern. Rufen Sie dazu einfach die Funktion auf und übergeben Sie ihr die ID.

function setCustomerChecked( id : text, checked : boolean ) do
   var n := number(replacex(id, "\D",""));
   var rec := record( Customer, n );
   rec.Checked := checked;
end;
var c := select Customer;
var isChecked := not first(c).Checked;
#{
   c.forEach( v => { setCustomerChecked( v, isChecked ) } );
}#;
c.checked;

Ausführungsfehler

Tritt in Ihrem Code ein Ausführungsfehler auf, so wird der Text der Fehlermeldung zurückgegeben:

Bild.png