Form.IO Renderer Angular 8 Load Form from variable - formio

I cannot get the form to render when passing the JSON string as a variable. If I paste the string into the HTML it works fine. Very confused.
My HTML:
<formio [form]="form" (submit)="onSubmit($event)"></formio>
I preload the JSON and pull from route data. My component:
export class FormIOViewerComponent implements OnInit {
constructor(private route: ActivatedRoute) { }
form:string='';
onSubmit(submission: any) {
console.log(submission);
}
ngOnInit() {
this.form=this.route.snapshot.data.Fields;
console.log(this.form)
}
}
The JSON string prints to console before the error, and again I can copy and paste the JSON string printed from the console into the HTML and it displays fine. The error seen in Chrome:
form-ioviewer.component.html:1 ERROR TypeError: Cannot read property '1' of null
at new Formio (Formio.js:213)
at Form.setForm (Form.js:185)
at new Form (Form.js:106)
at FormioComponent.push../node_modules/angular-formio/FormioBaseComponent.js.FormioBaseComponent.createRenderer (FormioBaseComponent.js:90)
at FormioComponent.push../node_modules/angular-formio/FormioBaseComponent.js.FormioBaseComponent.setForm (FormioBaseComponent.js:111)
at FormioBaseComponent.js:402
at ZoneDelegate.invoke (zone-evergreen.js:359)
at Zone.run (zone-evergreen.js:124)
at NgZone.runOutsideAngular (core.js:39572)
at FormioComponent.push../node_modules/angular-formio/FormioBaseComponent.js.FormioBaseComponent.ngOnChanges (FormioBaseComponent.js:398)

Turns out it won't except a JSON string, it MUST be a object. Something like:
export class formIO {
title:string;
name:string
components: string[]
}
Then pass the object to the form, not the string.

Related

Cannot read property 'type' of undefined ember and firebase

I am trying to retrieve data from my firestore using ember.js and emberfire.
i have a simple movie database. All that is in it right now is 1 document but for some reason when i try and retrieve the data, i keep getting "Cannot read property 'type' of undefined"! i understand that this is a JSONAPI issue but nothing seems to fix it.
My Route:
import Route from '#ember/routing/route';
export default class MovieRoute extends Route {
async model() {
this.store.findAll('movies').then(function(movie) {
console.log(movie);
});
}
}
My Model:
import Model, { attr } from '#ember-data/model';
export default class MoviesModel extends Model {
#attr('string') title;
}
Now it was my understanding that the default JSONAPISerializer is the default one but i tried adding a serializer anyway and my error changes to: Assertion Failed: normalizeResponse must return a valid JSON API document.
My adapter:
import FirestoreAdapter from 'emberfire/adapters/firestore';
export default FirestoreAdapter.extend({
// Uncomment the following lines to enable offline persistence and multi-tab support
// enablePersistence: true,
// persistenceSettings: { synchronizeTabs: true },
});
My Serializer:
import JSONAPISerializer from '#ember-data/serializer/json-api';
export default class ApplicationSerializer extends JSONAPISerializer {}
it is also my understanding that the way the JSON is to be accepted is:
{
data {
type: 'movies',
id: 1,
attributes {
title: 'ghostbusters'
}
}
}
so i also created a new document in the firestore, following this same format. Still no luck.
Can anyone point me in the right direction as to how to get the correct data returning from the firestore?
**edited --
error message:

Ionic 4 Angular 7 - passing object/data to another page [duplicate]

This question already has answers here:
Ionic 4. Alternative to NavParams
(8 answers)
Closed 4 years ago.
I would like to pass a JSON object to another page. What I've tried is to pass the JSON string using Angular router ActivatedRoute like this:
this.router.navigate(['details', details]);
and then retrieve it like this:
import { ActivatedRoute } from '#angular/router';
constructor(private activatedRoute: ActivatedRoute) {
}
ngOnInit() {
this.activatedRoute.params.subscribe(extras => {
console.log(extras);
this.JSONObject = extras;
});
}
It is possible to do it this way but what happened was the nested JSON objects becomes inaccessible. It turns into this string:
"[object Object]"
The stringified JSON object is fine and accessible before I pass it. Another problem is that it appends the JSON string to the url so it doesn't look that nice. From what I read as well, it is not a good practice to pass something more than just an id this way.
I am thinking of something like passing objects as intent extras between activities in Android. I've searched the documentations, forums, and previous stackoverflow questions but I didn't found any solution that enables me to achieve this. Is there any other way of passing objects between pages using Angular router in Ionic4?
I solved it using a service with a simple setter and getter just like in this question that I later found:
Ionic 4. Alternative to NavParams
First, I create a service with setter & getter:
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root'
})
export class NavExtrasService {
extras: any;
constructor() { }
public setExtras(data){
this.extras = data;
}
public getExtras(){
return this.extras;
}
}
Let's say I'm navigating from page A to page B, in page A:
this.navExtras.setExtras(extras)
this.router.navigateByUrl('page-b');
Then in Page B, I retrieve the extras this way:
this.location = navExtras.getExtras();
It works so far although I'm still not sure if there are better ways to do it..

Failing import in Polymer 2.x: ("The element ... is not defined")

I want to import an element and bind one of its properties. My import fails silently. I expect the value of userLocal to be an object. But, instead, userLocal is undefined.
my-app.html
<link rel="import" href="/src/app-state/state-user-local.html">
...
<state-user-local user-local="{{userLocal}}"></state-user-local>
...
<script>
/* #polymerElement */
class MyApp extends Polymer.Element {
static get is() { return 'my-app; }
static get properties() { return {
userLocal: {
type: Object,
notify: true,
},
...
}}
}
window.customElements.define(MyApp.is, MyApp);
</script>
with the following error message.
The element state-user-local is not defined
I know the import definition is correct because I am using VSCode and when I command+click the import it takes me to the correct file.
I know there is no problem with the <state-user-local> element itself because I successfully import it into other element/s in the app and obtain the expected value of userLocal there.
This problem sounds like what is described at the following links.
The element xxx is not defined (issue #54)
Recognize elements registered with MyElem.is (issue #540)
The first link discusses using "/* #polymerElement */ above the class" which is what I have tried (see above code) without success.
It seems to me that you didn't define the <state-user-local> element inside your file; you defined <my-app>. If you want to use the tag name <state-user-local> you need to define it as such.
<script>
class StateUserLocal extends Polymer.Element {
static get is() { return 'state-user-local'; }
static get properties() { return {
userLocal: {
type: Object,
notify: true,
},
...
}}
}
window.customElements.define(StateUserLocal.is, StateUserLocal);
</script>

Typescript - Get uninitialized properties after compilation

I am currently writing a wrapper around socket.io. Comming from a very object-oriented background, I want to implement the concept of Models in my framework/wrapper.
If you happen to know socket.io you might know that you get the data that is associated with an event as a parameter, now I have implemented a custom routing system where the handler of the route gets the data in an express.js like request object.
The idea is to have model classes that look something like this:
class XRequestModel
#v.String({ message: 'The username must be a string!' })
public userName: string;
}
And the route event might look something like this:
#RouteConfig({ route: '/something', model: XRequestModel })
class XEvent extends Route {
public on(req: Request<XRequestModel>, res: Response) {
// Handle Event
}
}
And to complete the example here is how the request object might look like:
class Request<T> {
public data: T;
}
Now generics in typescript are very limited since the type information is removed after compilation, I can not use the generic Request parameter ( which is the type of the model ) to get metadata from the model - Metadata, in this case, is the validation decorator. To overcome this issue I give a reference of the Model class to the RouteConfig of the RouteEvent, which is internally used and would allow me to create instances of the model, get the properties and so on...
The idea here is to give the handler of a route, a request object with pre-validated, typesafe data.
The thing holding me back from this, is the fact that unused properties, get removed after compilation by typescript, So I cannot get the metadata of the model. Initializing the class-property would solve this:
class XRequestModel
#v.String({ message: 'The username must be a string!' })
public userName: string = '';
}
But I think this makes for some very verbose syntax, and I dont want to force the user of this wrapper to init all the model properties.
An implementation side-note:
The user of the framework has to register the classes to a 'main' class and from there I can get the Route-class via decorator reflection.
When I try to get the properties of the model without initialized properties - First model example.
// Here the route.config.model refers to the model from the RouteConfig
Object.getOwnPropertyNames(new route.config.model());
>>> []
Here is what I get with initialized properties:
Object.getOwnPropertyNames(new route.config.model());
>>> [ 'userName' ]
Here a link to the GitHub repository: https://github.com/FetzenRndy/SRocket
Note that models are not implemented in this repo yet.
Basically, my question is: How can I get the properties of a class that has uninitialized properties after compilation.
The problem is that if no initialization happens, no code is emitted for the fields, so at runtime the field does not exist on the object until a value is assigned to it.
The simplest solution would be to initialize all fields even if you do so with just null :
class XRequestModel {
public userName: string = null;
public name: string = null;
}
var keys = Object.getOwnPropertyNames(new XRequestModel())
console.log(keys); // [ 'userName', 'name' ]
If this is not a workable solution for you, you can create a decorator that adds to a static field on the class and the walk up the prototype chain to get all fields:
function Prop(): PropertyDecorator {
return (target: Object, propertyKey: string): void => {
let props: string[]
if (target.hasOwnProperty("__props__")) {
props = (target as any)["__props__"];
} else {
props = (target as any)["__props__"] = [];
}
props.push(propertyKey);
};
}
class XRequestModelBase {
#Prop()
public baseName: string;
}
class XRequestModel extends XRequestModelBase {
#Prop()
public userName: string;
#Prop()
public name: string;
}
function getAllProps(cls: new (...args: any[]) => any) : string[] {
let result: string[] = [];
let prototype = cls.prototype;
while(prototype != null) {
let props: string[] = prototype["__props__"];
if(props){
result.push(...props);
}
prototype = Object.getPrototypeOf(prototype);
}
return result;
}
var keys = getAllProps(XRequestModel);
console.log(keys);

Submitting a form on a different component

I have created a model based form on a component, however the submit button is placed on a different component.
right now when you press the button this function is triggerd:
#Input()
form: any;
...
if(this.form.valid)
this.saveDefinition();
however I want to "send a signal" back to my component with the form if the form is invalid. If the form is invalid it should highlight all the invalid fields (Like it would when you would submit the form on the same component).
I've searched for a while and I can't even find out if this is possible, if it is possible can you guys help me get on my way?
thanks
you can use services, as follow:
form.service.ts file
#Injectable()
export class FormService {
onFormSubmitted = new EventEmitter<any>();
}
then register this service in the appModule providers appModue.ts file
providers: [
...
FormService
...
]
firstComponent.ts file
#Component({
...
});
export class FirstComponent implements{
constructor( public formService:FormService) {}
onFormSubmit(formData:any) {
this.formService.onFormSubmitted.emit(formData);
}
}
secondComponent.ts file
export class SecondComponent implements OnInit{
constructor ( public formService:FormService ) {}
ngOnInit() {
this.formService.onFormSubmitted.subscribe( (formData : any ) => {
this.onFormSubmit(formData);
})
}
onFormSubmit(formData : any) {
// your logic for submitting the form
}
}
the first and the second component have the same instance of FormService, so they have the same instance of the eventEmitter, the first component emitting the event when the form is submitting and the second component is listening to it.
its called cross-component communication using services.