Aurelia support for XML - aurelia

Will support be provided for XML file reads/writes? If I read the Aurelia docs correctly, Aurelia-fetch-client and aurelia-http-client, are configured for/expecting JSON response types (HTTP Services in Aurelia docs). I have a very large SPA conversion project and want to use Aurelia. However, all the page content and pointers are output in an XML document and mapped via GUIDs. Do I need to build a custom routine for XML to JSON for use with Aurelia?

The Fetch API specification currently doesn't have any methods to take/ convert the response stream as XML Document (https://developer.mozilla.org/en-US/docs/Web/API/Response#Methods). (The same fetch API is used by Aurelia if the browser supports it or it uses a polyfill (whatwg fetch) that implements matching logic to the API)
What you can do is get the stream as text and then parse the output with a library that can parse XML.
For example with jQuery's parseXML (https://api.jquery.com/jQuery.parseXML/) method:
import {autoinject} from 'aurelia-framework';
import {HttpClient} from 'aurelia-fetch-client';
import 'fetch';
import * as $ from 'jquery';
#autoinject
export class XMLFetchTest {
constructor(private http: HttpClient) {
http.configure(config => {
config
.useStandardConfiguration()
.withBaseUrl('/src/');
});
}
public activate() {
return this.http.fetch('test.xml')
.then(response => response.text())
.then(text => {
let doc = $.parseXML(text);
}));
}
}

Related

Fetch data from local JSON file with Nuxt Pinia

Is it possible to fetch a local .json. file using fetch()? I originally used the import method but the site's data doesn't get updated unless the page gets reloaded.
I tried doing this but it's not working:
stores/characters.ts
export const useCharactersStore = defineStore("characters", {
state: () => ({
characters: [],
}),
getters: {
getCharacters: (state) => {
return state.characters;
},
},
actions: {
fetchCharacters() {
fetch("../data.json")
.then((response) => response.json())
.then((data) => {
this.characters = data.characters;
});
},
},
});
app.vue
import { useCharactersStore } from "~/stores/characters";
const store = useCharactersStore();
onMounted(() => {
store.fetchCharacters();
});
Any help would be appreciated.
maybe a bit late but I have encountered the same problem migration from Nuxt 2 to Nuxt 3.
I'm certainly no expert on this, so if anyone finds a better way or if I'm totally wrong please let me know !
Whenever you import a json file in vue code they are imported as a module, that get's embedded within the code compilation on build (Vue Docs). Tu use json as a external file you need to place your json within the /public directory and use axios or fetch to load the file with a lifecyle hook.
This could be mounted() for options api or beforeMount()/onMounted() with composition api.
However some important annotations for this method.
If the json file you want to use in your app is not reactive, i.e. won't change, you should place this in the static folder of the nuxt app.
In your example you fetch '../data/...', this would imply the server knows the domain to look for. It can't call the route like this, you would have to give the full url if you put your json file in the static folder.
Set the baseUrl in the of your nuxt.config.ts, see docs for specifications.
Then you can access the static folder with your .env variables
--> $fe
Then in you data script you can access your json file
async getJson(some parameters){
const data = $fetch('your domain with the runtimeConfig composable').then((data)=>{ console.log(data)});
Sidenote you can also load the file from the server-side using fs.readFile
read more about this in this awesome post here

Nuxt avoid import of client-side script for server-side rendering

In my nuxt.js application, I have a script that imports an NPM package which is only compatible with browser contexts (it references document, location, window, etc.)
Is there a way to exclude this from SSR?
import thing from "#vendor/thing"; // causes `document not defined` error
export default showThing(){
if (process.client) {
thing();
}
}
I can use the method with process.client but this file is still imported in my components.
You could import it dynamically rather than in every context.
As explained in my answer here: https://stackoverflow.com/a/67825061/8816585
In your example, that would be something like this
export default showThing(){
if (process.client) {
const thing = await import('#vendor/thing')
thing()
}
}

How to use ActivatedRoute in Angular 5?

I am trying to do exactly the same thing as in this post: Angular 4 get queryString
I am using Angular 5.2.5.
ActivatedRoute seems to be the thing to use to retrieve querystring values off the URL when the user first visits the website. However, I am unable to figure out what I need to import to be able to use ActivatedRoute.
Could someone specify exactly what needs to be added to the app.module.ts file, and the component.ts file where I am trying to use ActivatedRoute?
This post specifies adding routing to the imports array of the #NgModule: No provider for ActivatedRoute - Angular 2 RC5. However, I don't have an app.routing.ts file. Do I have to create an app.routing.ts file to use ActivatedRoute?
ActivatedRoute Contains the information about a route associated with a component loaded in an outlet.
It can also be used to pass data from one component to another component using route such as Id, flag, state etc.
http://localhost:4200/quiz/edit_quiz/032
032 being id of the quiz you wanna edit.
Get this id in your component(in my case let it be edit_quiz.compontent.ts) to use by using Activated Route.
Step 1: Import ActivatedRoute from Router module.
import { ActivatedRoute } from '#angular/router';
Step 2: Inject ActivatedRoute in constructor.
constructor(private activatedRoute: ActivatedRoute) { }
Step 3: Get id on a local variable named quizId in ngOnInit(){}
ngOnInit() {
this.quiz_id = this.activatedRoute.snapshot.params['id'];
}
Now we have id in edit_quiz.component.ts to use.
I made the two changes Arun suggested. Then, to fix the "No provider for ActivatedRoute" error, I made the changes shown below.
1) I added this line to the app.module.ts:
import { RouterModule } from '#angular/router';
2) I added this line to the imports array of the #NgModule in app.module.ts:
RouterModule.forRoot([])
This article gave me the fix: Angular error: no provider for ActivatedRoute
Now it compiles. Hooray!
You need to import ActivatedRoute from #angular/router like
import { ActivatedRoute } from '#angular/router';
then add this line to the imports array of the #NgModule in app.module.ts:
imports:[
........,
RouterModule.forRoot()
],
then you can use any where as below:
constructor(private route: ActivatedRoute) {
console.log(route.snapshot.queryParamMap); // this
}
// or
queryString : string;
getQueryString(){
this.queryString = this.route.queryParamMap.get('myQueryParam');
}
No. You don't need app.routing.ts if you don't have to navigate pages within your app.
How to Get Route Parameters:
The Angular Router provides two different methods to get route parameters:
a. Using the route snapshot(ActivatedRoute),
b. Using Router Observables
ActivatedRoute in Angular:
Provides access to information about a route associated with a component that is loaded in an outlet
Step-1 Import the ActivatedRoute interface
import { Router, ActivatedRoute } from '#angular/router';
Step-2 Inject the ActivatedRoute in Constructor
constructor(private route: ActivatedRoute, private router: Router) {}
Step-3 To fetch a employee object by the given id and assign that object to its local employee property.
ngOnInit() {
this.employee = new Employee();
this.id = this.route.snapshot.params['id'];
Note: Property Description
snapshot: The current snapshot of this route
ActivatedRoute
I'm late to the conversation but hope the following works for the future programmers who encounter the same issue.
import the ActivatedRoute
import { ActivatedRoute } from '#angular/router';
Inject the dependency injection
constructor(
private route: ActivatedRoute,
) { }
and to grab the id from the link you can use the following
ngOnInit() {
this.route.paramMap.subscribe(params => {
this.product = products[+params.get('productId')];
});
}

Hot to add POST interceptor to aurelia http client

Basically, the question says it all :). The scenario is as follows: I have some python models that are being passed between the browser, and the server. Python convention for naming things is to use underscores, and js convention is to camelCase everything. So I figured, I'd just create an http request interceptor to convert between python_models and jsModels. Is there a simple way to accomplish that?
I'm also looking for a way to do the inverse, so camelCase to that-case :)
If you're using aurelia-http-client, you can use a reviver.
import {HttpClient} from 'aurelia-http-client';
import {Person} from './models';
export class PersonService {
constructor(){
this.http = new HttpClient().configure(x=> {
x.withReviver((k,v) => {
return typeof v === 'object' ? new Person(v) : v;
});
});
}
getPeople(){
return this.http.get('/people');
}
}
This only works for aurelia-http-client and not aurelia-fetch-client. It has been talked about in the fetch spec, but I don't believe it is currently implemented.
Check the following for more information:
(my) Best Practices in Aurelia: The Model
https://github.com/whatwg/fetch/issues/104

How to dynamically mock ES6 modules with SystemJS?

I have a single-page application written in ES6. The code in transpiled server-side into classic javascript by babelJs, then loaded by SystemJs.
Javascript present in my html file:
System.config({
baseURL: '/js',
meta: {
'/js/*': { format: 'cjs' }
}});
System.defaultJSExtensions = true;
System.import("index.js")
.catch(function (error) {
console.error(error)
});
index.js:
import f1 from 'file1';
import f2 from 'file2';
// code here ...
Everything works fine. index.js is loaded, and all import statements are correctly executed.
Now, I want to create some pages with mocked ES6 modules, for testing purpose. My goal is to display pages by replacing model classes (contained in ES6 modules) with other static test classes.
Let's say I have 3 files: real_model.js, fake_model.js and component.js. component.js import the real model (import Model from 'real_model';).
How can I replace the real model by the fake one (in the component) dynamically ?
It's been a while since this question was posted, but maybe this solution might still be of help to anyone else.
With SystemJS it is possible to create a module on-the-fly using System.newModule. Then you can use System.set to overwrite existing modules with the new one. In our tests we use the following helper function to mock existing modules:
function mockModule(name, value) {
const normalizedName = System.normalizeSync(name);
System.delete(normalizedName);
System.set(normalizedName, System.newModule(Object.assign({ default: value }, value)));
}
Then, e.g. inside the beforeEach callback, we assign the mock and then import the module to be tested using System.import:
let [component, fake_model] = [];
beforeEach(() => {
// define mock
fake_model = { foo: 'bar' };
// overwrite module with mock
mockModule('real_model', fake_model);
// delete and reimport module
System.delete(System.normalizeSync('component'));
return System.import('src/testing').then((m) => {
component = m.default;
}).catch(err => console.error(err));
});
// test your component here ...
A big advantage of this approach is that you don't need an additional mocking library and it works solely with SystemJS.