When I try to execute your code in development, I have some errors that are directly related to your code. Maybe in production they’re obfuscated:
The code repeats the same pattern, that leads to errors:
- A private
@tracked
property
- A getter that will first test the value of this tracked property, and then initialize it if uninitialized.
This leads to this error:
index.js:172 Uncaught (in promise) Error: Assertion Failed: You attempted to update _apiUrl
on MyComponent
, but it had already been used previously in the same computation. Attempting to update a value after using it in a computation can cause logical errors, infinite revalidation bugs, and performance issues, and is not supported.
In your code, I replaced the access to the user ID to make it work:
import { alias } from '@ember/object/computed';
export default class MyComponent extends Component {
@service currentUser;
// This uses internal code from Forest Admin, so it's subject to change
// but it is quite stable so it won't change often
@alias('currentUser.id') userId;
The API URL can be retrieved as well directly from lianaSession
, or computed with your method:
// I keep this as a reference as it can be used in other contexts
@computed()
get apiUrl() {
const [env = null] = location.href.match(/DEV-[A-Za-z]*|UAT|Production/gi);
switch (env) {
case "UAT":
return "https://uat.foo.bar";
case "Production":
return "https://prod.foo.bar";
default:
return "http://localhost:3000";
}
}
// A simpler version that uses Forest Admin's internal code
// so it is subject to change, but quite stable
@alias('lianaSession.currentEnvironment.apiEndpoint') apiUrl;
The usage of @computed
ensures that the value is only computed once.
And the token can be retrieved using lianaSession.authToken
as explained in another topic.
To wrap up, this code should work:
import Component from "@glimmer/component";
import { inject as service } from "@ember/service";
import { action, computed } from "@ember/object";
import { tracked } from "@glimmer/tracking";
import { alias } from '@ember/object/computed';
import {
triggerSmartAction,
deleteRecords,
getCollectionId,
loadExternalStyle,
loadExternalJavascript,
} from "client/utils/smart-view-utils";
export default class MyComponent extends Component {
@tracked _token = null;
@tracked _apiUrl = null;
@service currentUser;
@service lianaSession;
@alias('currentUser.id') userId;
@alias('lianaSession.authToken') token;
@alias('lianaSession.currentEnvironment.apiEndpoint') apiUrl;
@action
toggleFullScreen() {
const iframeContainer = document.getElementById("notes-iframe-container");
const wrapper = document.getElementById("notes-wrapper");
if (iframeContainer?.classList?.contains("fullscreen")) {
const fragment = document.createDocumentFragment();
fragment.appendChild(iframeContainer);
wrapper.append(fragment);
} else {
const fragment = document.createDocumentFragment();
fragment.appendChild(iframeContainer);
document.body.prepend(fragment);
}
iframeContainer?.classList?.toggle("fullscreen");
}
}