I am trying to Integrate AEM forms with Angular. I have my AEM forms url which will send the data in HTML and that HTML I have to render into Angular.
I am facing two issues :
The AEM site is hosted in different domain. So for that I added the header to stop cross domain issue and as the response I am getting is in html I have to set the response type as HTML. BY doing so the angular is able to render the HTML correctly but the the css and js are not loading properly as the response HTML has the the relative path of css and js.
As aforesaid I am using two extra parameter by build is failing by saying that only 1-2 parameter is expected in get.
TS FILE
#Component({
selector: 'app-embeddedforms',
templateUrl: './embeddedforms.component.html',
styleUrls: ['./embeddedforms.component.css']
})
export class EmbeddedformsComponent implements OnInit {
constructor(private http: HttpClient) {}
private url = 'http://localhost:4505/content/forms/af/formspoc/baggage-calculator.html';
ngOnInit() {
this.http.get(this.url, {
responseType: 'html'
}, {
headers: {
'Access-Control-Allow-Methods': 'GET',
'Access-Control-Allow-Origin': '*'
}
}).subscribe(data => {
document.getElementById('formdata').innerHTML = data;
});
}
}
html CODE
<ul>embedded forms Start Here
<li>Here we are trying to embedded the forms with angular </li>
</ul>
<div id="formdata"></div>
The expected result is that angular site should be able to embed the aem form with all it's css, js and functionality but this is not happening.
Related
Is it possible to return JSON result from Angular instead of the HTML template coz we want to build something similar to a API-server? Thanks.
Here is the example that return the HTML template, how can we just return JSON without using template?
What I want to return is just a simple json result instead of HTML.
{"ID" : "1", "Name" : "Apple"}
Here is the code.
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'app-noresultsfound',
templateUrl: './noresultsfound.component.html',
styleUrls: ['./noresultsfound.component.css']
})
export class NoresultsfoundComponent implements OnInit {
#Input() txtval: string;
constructor(private app: AppConstants) { }
noresultsfound = this.app.noresultsfound;
ngOnInit() {
}
}
Alex
I think, he meant that pure JSON should be returned to who ever requested it by endpoint request. At least i faced something like this.
For static json, i've found an answer: https://github.com/angular/angular-cli/issues/5029
bresleveloper commented on 6 Jul 2018
1. ng-build with your index.html set properly with its components. (or conditional app-components)
2. rename and copy the rendered to (for example) /src/search.html
3. in angular.json (angular-cli.json for pre v5) find "assets":
"assets": [
"src/favicon.ico",
"src/search.html",
"src/assets"
],
browse localhost:4200/search.html
enjoy :)
Interesting part comes when u try to generate that json somehow, with browser not being involved - like some automatic service sends a request to some angular endpoint, like: hosname/statistics and in response, it receives a json which depends on number of pictures and headers on this current hosname, like {siteName: 'test', pictures: 10, headers: 1}.
I have an rest api which i could use post and get requests. But when i want to use put and delete request it returns error 403. But also when i try to put and delete with Postman app (an app for json requests) all is works well. Im really confused. Let me prove the problem with some screenshots.
(Im censored links for security, sorry for that)
Chrome console;
Postman App;
Any my put code;
/** PUT: update the firm on the server */
updateFirm (firm: Firm): Observable<any> {
console.log(firm);
return this.http.put(this.firmUrl+"put/"+String(firm.id), firm, httpOptions).pipe(
tap(_ => console.log(`updated firm id=${firm.id}`)),
catchError(this.handleError<any>('updateFirm'))
);
}
I will be very appreciated if you could help me. Have nice day
I had a similar situation and found out that Angular 2 performs a OPTIONS method before a POST is done! OPTIONS was missing in "Access-Control-Allow-Methods".
If I check your log, then I think that you should also allow OPTIONS:
With angular, and perl as a backend, I had to allow the following:
-"Access-Control-Allow-Methods" => 'GET,POST,PATCH,DELETE,PUT,OPTIONS',
Proxy solves your problem.
A nice and fast solution could be to borrow one (like https://cors-anywhere.herokuapp.com) to test then do your own.
Here is an example :
import { Component, OnInit } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
#Component({
selector: 'app-analyzer',
templateUrl: './analyzer.component.html',
styleUrls: ['./analyzer.component.scss']
})
export class AnalyzerComponent implements OnInit {
res;
constructor(private http: HttpClient) {
this.getDeck().subscribe(res => {console.log(res); this.res = res; });
}
ngOnInit() {
}
getDeck() {
const headers = new HttpHeaders({
'X-Requested-With': 'XMLHttpRequest'
});
return this.http.get('https://cors-anywhere.herokuapp.com/https://www.keyforgegame.com/api/decks/30763530-041c-4e15-b506-3456e79141d2/',
{headers: headers}
);
}
}
It looks like a CORS error, you are doing the http request from your local machine on localhost to the backend on a different URL. The only way to solve this would be to allow requests from different origins on the backend. Or possibly to run the backend on your local machine.
Your problem is about CORS for HTTP OPTIONS request.
Indeed, before the execution of the HTTP PUT request, your client has to make a OPTIONS request, in order to add your httpOptions variable, which contains your header.
So you have to authorize the execution of OPTIONS request in the code of your server.
EDIT: I am using AngularDart 5 and i have created an issue on GitHub https://github.com/dart-lang/angular/issues/1311
I have got this AngularDart Component:
#Component(
selector: 'todo-list',
template: '<div>{{todos | async}}</div>',
directives: [coreDirectives],
pipes: const [AsyncPipe])
class TodoListComponent {
Stream<List<TodoItem>> todos =
new TodoListViewModelImpl(new TodoServiceImpl()).output.todoItems;
}
As you can see, this is working like expected. The template displays an empty list, because there has not todo item been inserted yet.
However i do not want to have a todos attribute to access output.todoItems.
I want to access output.todoItems directly from the template using dotted notation:
#Component(
selector: 'todo-list',
template: '<div>{{viewModel.output.todoItems | async}}</div>',
directives: [coreDirectives],
pipes: const [AsyncPipe])
class TodoListComponent {
TodoListViewModel viewModel =
new TodoListViewModelImpl(new TodoServiceImpl());
}
BUT this does not work actually. I dont get any error messages whatsoever.
I am trying to fetch data from a local json file so that i would manipulate the data in the view (if u choose UnitOne the only 'roles' u can pick are 'role1','role2','role3' etc.)
So i build a sample application just to demonstrate the whole deal.
Basically I'm getting this error message:
Error: Uncaught (in promise): SyntaxError: Unexpected token < in JSON
at position 0 SyntaxError: Unexpected token < in JSON at position 0 at
JSON.parse () at Response.Body.json
here's the code Link
Your http call is not getting the JSON file because it does not live at http://localhost/data.json. That call is returning some HTML, which is why you get the error you get.
You can import the JSON file using TypeScript instead of trying to request it via HTTP.
import { Component, OnInit } from '#angular/core';
import 'rxjs/add/operator/toPromise';
import { Http } from '#angular/http';
import { RootObject, Parameter, Infos, Info, ValidValues, Condition} from './data.model';
import json from './data.json'
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
data: RootObject;
print: string = '';
constructor(private http: Http) { }
ngOnInit() {
this.data = json as RootObject;
this.print = this.data.parameters[1].keyParameterName;
}
}
Here is a working version.
There may be prettier ways to write the code, but I'll leave that up to you. :)
If you absolutely must request the JSON via HTTP, then I recommend you place it in your assets directory and make a call to /assets/data.json instead. That might work. Either that or use a CDN/external URL to request it from. But keep in mind you would need to have CORS enabled on that server or your request will be blocked by your browser.
The only issue here is your json file is not within assets folder.
You should move that file to your assets folder , and then try with the same code , and it will work.
Keep your file in the root of assets , as you are trying to fetch
./data.json ,
if you move to some of folder name asdf within assets , then you
need to change it like ./asdf/data.json
I'm working on an Angular 2 application, and I'm trying to use JSON data, either local/mocked or fetched via HTTP, and display it on a component. I have an injectable service that will do the fetching/mocking -
import { Injectable } from 'angular2/core';
#Injectable()
export class TestService {
testString:string = "";
testDetails: string = "";
constructor() { }
getTestDetails(): Promise<string> {
this.testDetails = {
"status": "success",
"message": "Data save successful",
"data": {
"Random_Data_1": "Random Data 1",
"Random_Data_2": "Random Data 2"
}
};
return Promise.resolve(JSON.stringify(this.propertyDetails));
}
}
And then I have a component that uses the service via Dependency Injection -
import { Component, OnInit } from 'angular2/core';
import {TestService} from "./test.service";
#Component({
selector: 'test',
templateUrl: './test.component.html',
styleUrls: []
})
export class TestComponent implements OnInit {
testDetails: string = "";
constructor(private testService: TestService) { }
ngOnInit() {
this.display();
}
display(): void {
this.testService.getTestDetails()
.then(
testDetails => {
this.testDetails = JSON.parse(testDetails);
},
errorMessage => {
console.error("Something failed trying to get test details");
console.error(errorMessage);
}
);
}
}
The component HTML -
<div class="content">
<p> Test Details </p>
<p> {{ testDetails.data.Random_Data_1 }} </p>
</div>
The problem is, the HTML is erroring out trying to display the items in the testDetails JSON. I initially used it with md-tabs, so the first try would error out, but the other tabs would read the data fine. Also, the ngOnInit would be called twice when the error occurs. I have narrowed it down to the data coming in and the object types that is causing me the headache.
I know I can create a Details class and declare testDetails of type Details, and then map the JSON data into the class, but the thing is, I want to work with generic data, and only know a few components that will be present in the data. Is there a way to read the JSON, and use the data without having to define a separate class for each scenario ?
I have a plunker with the most basic stuff set up. The actual setup runs fine on my local system up until where I try to access the JSON data in the HTML, at which point the browser throws a cryptic error. The skeleton code doesn't even run on Plunker. That said, the structure in the Plunker defines the structure of my app and the data flow. Plunker with the basic setup
What is the best way to achieve this ? What is the standard/best practice to do this ?
Throwing another option out there, since you asked about best way to achieve this. Might not be the best idea, this is subjective ;) But if I were you...
Thinking about the future, where you will use real backend, it could be nice to use mock json file. If/when you move over to a real backend, you wouldn't basically need to change anything else but the url of the requests :)
So I set up a simple example for you. Here I used Observables, but you can use Promises if you prefer that. Here's more info on HTTP if you want/need to read up on that. Most important thing is that you have the HttpModule imported in your app module.
You have your file with JSON and in your service make http-requests to that:
getTestDetails() {
return this.http.get('src/data.json')
.map(res => res.json())
}
Your display-method:
display() {
this.testService.getTestDetails()
.subscribe(data => {
this.testDetails = data;
});
}
And in the template use the safe navigation operator to safeguard null/undefined values:
<div class="content">
<p> Test Details </p>
<p> {{ testDetails?.data?.Random_Data_1 }} </p>
</div>
Here's a
Demo
As said, this is to give another approach on how to implement the things you want to achieve, and this would probably be my preferred way :)
Use
<p *ngIF="testDetails.data.Random_Data_1 "> {{ testDetails.data.Random_Data_1 }} </p>
This is because there is no data initially.Hope this helps you.