I am hosting xtext's orion editor using iframe in my angular application. I need to save the content written from my angular application side to a backend (Java application). Can anyone help me with what API calls or approach should I make from my angular side so that I can save the content written in the editor.
What I have already done :
1 .I tried extracting the content from the iframe from my angular side , but the data so extracted is partial as it only extracts data what is only visible through the iframe at once and not the whole content which one has to scroll to view .
2 . I tried making 'save' API calls that the xtext makes while saving, but it requires some stateId as its request body . I need to understand what is this state Id and how is it evaluated ?
I am making this call from my angular application
_this.saveEditor = function(args) {
var params = {
requiredStateId: args.stateId
}
_this.saveUrl = XTEXT_URL + '/save?resource=' + args.resourceId;
return $http({
method: 'POST',
url: _this.saveUrl,
data: params
});
};
my request body is :
{"requiredStateId":"-80000000"}
And this is the state Id i am obtaining by making a prior load api call which.returns state Id in its response.
may this snipped can help you, i dont know how you can wire this up with your stuff though
require(["orion/code_edit/built-codeEdit-amd"], function() {
require(["xtext/xtext-orion"], function(xtext) {
var editors = xtext.createEditor({
baseUrl: baseUrl,
syntaxDefinition: "xtext-resources/generated/mydsl-syntax"
}).done(function(editorViewer) {
$("#save-button").click(function() {
editorViewer.xtextServices.saveResource();
});
$("#log-button").click(function() {
console.log(editorViewer.xtextServices.editorContext.getServerState());
});
});
});
});
where i do the simple log you can query and then call save manually.
Related
I'm working on a ASP.NET MVC project that uses some jQuery on the client side. I have a jQuery call like this, which works correctly:
$.post($('form').attr("action"), $('form').serialize(), function(data){
// Deal with the data that came back from the ASP.NET MVC controller
}
I want to do the exact same call, except I also want to send in a custom header. I am able to successfully create and send a custom header like this:
var token = $('input[name="__RequestVerificationToken"]').val();
var headers = {};
headers['__RequestVerificationToken'] = token;
$.ajax({
url: "/report_observation/" + submitType,
cache: false,
type: "POST",
data: {
'viewModel': $('form').serialize(),
},
headers: headers,
success: function (data) {
// Deal with the data that came back from the ASP.NET MVC controller
},
error: function (response) {
alert("Error: " + response);
}
});
There are two problems with this second bit of code. One is that I have to make a custom url to go to the correct controller, and I don't know of a way to simply use $('form').attr("action") to automatically go to the correct place.
The second -- and bigger -- problem is that I'm not able to pass over the form data with $('form').serialize() as I could in the one liner $.post example. Doing a #Html.Raw(Json.Encode(Model)) in my Razor cshtml file doesn't send over the model for the whole form, presumably because this code is within a partial view that doesn't know the state of the models in the other partial views that make up this form.
Anyway, I'm thinking there must be an easy way to take this code...
var token = $('input[name="__RequestVerificationToken"]').val();
var headers = {};
headers['__RequestVerificationToken'] = token;
...and incorporate the headers property into this bit of code:
$.post($('form').attr("action"), $('form').serialize(), function(data){
// Deal with the data that came back from the ASP.NET MVC controller
}
However, I can't figure out the correct syntax. Any ideas?
OK, I figured it out. The second example can indeed work if the data field looks like this:
data: $("form").serialize(),
In other words, I had to NOT assign it to the viewModel parameter.
yes, for the second problem use that dev5000 says, and, for the URL, simply get the value for the attribute action fo the form and use it:
var url = $("from").attr("action");
$.ajax({
url: url,
...
})
I have a form
form#form-reflow(action='/', method='post',
onsubmit="docreflow()")
input#textinp(type="text", name="textinp")
input#submit(type="submit", name="submit")
that runs the following ajax client script to send the form data to Express.
function docreflow() {
$('#form-reflow').on('submit', function (evt) {
evt.preventDefault();
$.post($('#form-reflow').attr( 'action' ),
{
data: $("#textinp").val(),
headers: {'X-Requested-With': 'XMLHttpRequest'},
dataType: 'text',
accepts: {
text: 'text/plain'
},
})
.done(function onDone (data) {
console.log("returned data is: ");
var data = JSON.parse(data).data;
console.log(data);
$('#form-reflow').html(data);
}
)
.fail(function onFail(err) {
$('#form-reflow').html("<p> There Wazza Khold Dey</p>");
});
})
}
I want the server POST method to not reload the page.
Instead I want to know how can I receive the data on the client back as an html:
this is jade btw.
div#ajaxMsg
p It actually works!
p Data is "#{data}"
from the controller method while it does something like
res.render('afterReload.jade', {some data...})
The page should not reload instead on ajax done it should
just include that rendered html snippet here:
$('#form-reflow').html(data);
For eg, consider you would write an AJAX api to New york times
the NYT api uses a jsonp to sendback with your defined Callback
and I can just include that data in my current page.
Lets say I do a json rendering only. from the server I send the json data
and on success, the function will append that data on client side as I wish.
How can I do a 'No Reload' AJAX server to client response?
Feel free to ask me for further clarity.
According to this
changing the evt type to change doesn't affect the behaviour. it still reloads the page.
Both the current and POST page controller routes are defined to be '/'
UPDATE
I have removed the html5 onsubmit event. no need:
form#form-reflow(action='/', method='post')
input#textinp(type="text", name="textinp")
input#submit(type="submit", name="submit")
UPDATE #2
This does not solve my problem
even if I add a return false; at the end of the function call in that script,
the controller function:
function ajaxReq(req, res) {
console.log(req.body);
if (req.accepts('text')) {
//#TODO: do something with this to doc reflow instead page reload
res.json({data: req.body.textinp});
}
};
still reloads the page.
I disagree with #mccannf for pointing out that its a duplicate.
No it doesn't solve my problem. Try implementing an express app. where you render something at '/' with a form that posts with ajax to server and it should render back an html snippet from, say a .jade/template file, as an html chunk back to the successful ajax call and replace the current html in place of form.
That is the core of my problem.
UPDATE #3
I have been able to check this out and do a rendering but its not doing a partial rendering.
Anyone knows how to use it in express 4 without loading the whole page and
returning value to ajax call?
This solves my problem and now it is a single working page:
script(src="js/scr.js")
the view is this and something more:
form#form-reflow(action='/scr')
input#textinp(type="text", name="textinp")
input#submit(type="submit", name="submit")
scr is this without a function wrapper. for eg:
$('#form-reflow').submit(function (e) {
e.preventDefault();
var posting = $.post( $('#form-reflow').attr( 'action' ),
{data:$("#textinp").val()
})
posting.done(
function onDone (val) {
$("#form-reflow").removeAttr('action');
$("#form-reflow")
.html("<p> hello baby " + val.data + "</p>");
});
return false;
});
the controller is :
some_controller = function some_controller(req, res) {
if (req.accepts(['json', 'jsonp'])) {
res.setHeader("Content-Type", "application/json");
var json_data = {data: req.body.data,
};
res.jsonp(json_data);
}
};
app.use('/', some_router);
some_router.post('/scr',some_controller);
So this works without rendering to a new page.
I found this tutorial on how to build cascading dropdowns in MVC with Razor syntax. I followed the tutorial and got it working perfectly in it's own project. But now that I am trying to port it over to my actual project, I am getting an error when the first dropdown is changed. As per the script, an alert pops up that says:
Failed to retrieve states: [object Object]
I have no idea what [object Object] means. My guess is that the error has something to do with the Url:
url: '#Url.Action("GetStates")
But that's just a guess. The major difference between the example project and the real project is that the real project uses routing for the URL Here's the entire script:
<script src="~/Scripts/jquery-1.10.2.js" type="text/javascript"></script>
<script src="~/Scripts/jquery-1.10.2.min.js" type="text/javascript"</script>
<script type="text/javascript">
$(document).ready(function () {
//Dropdownlist Selectedchange event
$("#Country").change(function () {
$("#State").empty();
$.ajax({
type: 'POST',
url: '#Url.Action("GetStates")', // we are calling json method
dataType: 'json',
data: { id: $("#Country").val() },
// here we are get value of selected country and passing same value as input to json method GetStates.
success: function (states) {
// states contains the JSON formatted list
// of states passed from the controller
$.each(states, function (i, state) {
$("#State").append('<option value="' + state.Value + '">' +
state.Text + '</option>');
// here we are adding option for States
});
},
error: function (ex) {
alert('Failed to retrieve states: ' + ex);
}
});
return false;
})
});
EDIT AFTER:
While watching the network traffic in Chrome's developer tools, I did this in the stand-alone project that works, and saw this entry with the title "GetStates" and this URL: http://localhost:50266/CustomerFeedback/GetStates.
I did it again in my actual project, and this time I see an entry that says "45/" with this URL: http://localhost:65303/PatientSatisfactionSurvey/45/.
I think this confirms my suspicion that the URL is the problem. I'm going to have to play around with figuring out how to make this URL valid.
Another Edit:
On the project that works, if I go to: http://localhost:50266/CustomerFeedback/GetStates
I get this:
Server Error in '/' Application.
This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.
This is expected as I am trying to hit that actual method. Meaning, I can go to the URL of the method. But when I try and do the same thing in my project: http://localhost:65303/PatientSatisfactionSurvey/GetStates, it just loads the page. That's because it thinks that "GetStates" is a parameter, and not a method.
I CAN NOT figure out what the URL of the method would be!! The dang routing is getting in the way....
routes.MapRoute(
"PatientSatisfactionSurvey",
"PatientSatisfactionSurvey/{ApptID}/{*LanguageCode}",
new { controller = "Forms", action = "PatientSatisfactionSurvey" },
namespaces: new[] { "GEDC.Controllers" }
);
Try changing #Url.Action("GetStates") to:
#Url.Action("ControllerName", "ActionName")
Probbaly something like #Url.Action("PatientSatisfactionSurvey", "GetStates")
which will generate a URL like ~/PatientSatisfactionSurvey/GetStates/5 where 5 is the ID that it is grabbing from the html element with the ID of Country.
Finally worked this out. My problem was three fold. First, when I looked at the HTML source, it turned out this:
url: '#Url.Action("GetStates")', // we are calling json method
was rendering as this:
url: ''
Once I took out the razor syntax, it at least rendered properly in HTML. However, it was still getting the wrong URL. Because the route map I was using had parameters in it, I ended up just creating a whole new route map for this one method:
routes.MapRoute(
"GetStates",
"GetStates",
new { controller = "Forms", action = "GetStates" },
namespaces: new[] { "xyz.Controllers" }
);
Then I changed the URL line in the javascript to look like this:
url: 'GetStates'
But the problem with this was that it was just appending /GetStates to the end of whatever URL I happened to be on. If put the entire fully qualified URL in there, like this...
url: 'http://localhost:65303/GetStates'
That worked. But for obvious reasons, that URL is not a long term solution. So, using this thread, I finally found the answer. I was able to get the fully qualified URL of this method GetStates() as follows:
// Get the fully qualifed URL of the FollowUpOptions() method for use in building the cascading dropdown
UrlHelper Url = new UrlHelper(System.Web.HttpContext.Current.Request.RequestContext);
myModel.ullDropdownUrl = Url.Action("GetStates", "Forms", new { }, this.Request.Url.Scheme);
Then I was able to do this in the javascript, which FINALLY got it all working:
url: '#Model.fullDropdownUrl'
I am creating a basic piece of functionality to allow users to send their location to a server which then queries a database and returns locations near to them. I am using the below jQuery .ajax wrapper to POST data to the server. This takes the form of a latlon point which is then used as the basis for a geosearch in MongoDB using nodejs and express on the backend. The results of the search are then intended to be returned to the client and rendered by the createMapListings function.
The /find page is initially rendered through a GET request to the database via mongodb separate from the below code. However subsequent to initial rendering, I then want to return results dependent on the location provided.
The POST method works fine and the location is posted to the server, with the search results being returned as I can print contents out through the console log.
However, I then want to render the results on the client-side. As mentioned, the results of the search render in the console, but when I attempt to pass through to the client, I can render the data itself (in the form of an array of objects) in the #output div, but the createMapListings function does not seem to catch the data.
In fact, the below function appears to be called but prints out over a thousand rows with the data that should be caught described as 'undefined'. I have tried to use res.render and res.redirect, but in the first case, the view renders in the div (which I suppose is expected) and the redirect fails.
The createMapListings function works fine when a simple GET request is made to the server, for example, for all objects in a collection, using ejs template. However, I think the issue here may be a combination of a POST request and then wanting to pass the results back to the AJAX request using the complete callback.
I apologise if the below code is somewhat obtuse. I’m definitely what you would call a beginner. I appreciate the above functionality may not possible so if there is a better way, I would of course be open to it (res.direct perhaps).
Here is the relevant client side script:
$(document).ready(function(){
$("#geolocate").click(function(){
navigator.geolocation.getCurrentPosition(geolocate, function(){
});
});
});
function geolocate(pos){
var latlonpt = [];
var x = pos.coords.latitude;
var y = pos.coords.longitude;
latlonpt.push(x);
latlonpt.push(y);
var obj = {
userlocation: latitudelongitudept
};
$.ajax({
url: "/find",
type: "POST",
contentType: "application/json",
processData: false,
data: JSON.stringify(obj),
complete: function (data) {
$('#output').html(data.responseText);
$('#infooutput').children().remove();
createMapListings(data.responseText);
}
});
};
function createMapListings(maps) {
for (var i = 0; i < maps.length; i++) {
var url = maps[i]._id;
var fullurl = "<a href='/show?id=" + url + "'>Route</a></div>";
var title = "<div>" + maps[i].title + " - " + fullurl +"";
$('#infooutput').append(title);
};
};
</script>
Here is the relevant route used in a basic express app to handle the post request made by the above .ajax wrapper.
exports.findbylocation = function(req, res) {
console.log(req.body.userlocation);
var userlocation = req.body.userlocation;
Map.ensureIndexes;
Map.find({loc :{ $near : userlocation }}, function(err, maps) {
if (err) {
console.log(err)
}
else {
var jmaps = JSON.stringify(maps);
console.log(jmaps);
res.send(jmaps);
}
});
};
By convention, the data variable name in an $.ajax callback signature refers to the parsed HTTP response body. Since your callback is on complete, we're actually passed the XMLHttpRequest used, by convention called xhr. You rightly grab the responseText property, but this needs parsing to be useful. So long as we take care over our Content-Type's and don't explicitly disable processData, jQuery will do the encoding/unencoding for us - we just deal with objects. This is a good thing, since the transport format isn't usually of any particular importance to the application logic. If we use res.json(maps) in place of res.send(jmaps), we can write our call more simply:
$.ajax({
url: '/find',
type: 'POST',
data: obj,
success: function(data) {},
error: function(xhr, text, err) {}
});
Here data is a Javascript object already parsed and ready to use. We also use a default application/x-www-form-urlencoded request rather than explicitly setting a contentType. This is the same as far as express is concerned: it will just be parsed by urlencoded instead of json.
Assuming you solved your client-sie problem.
As you are using express there is no need for JSON.stringfy,
you can use res.json(maps).
I have two HTML pages that work in a parent-child relationship in this way:
The first one has a button which does two things: First it requests data from the database via an AJAX call. Second it directs the user to the next page with the requested data, which will be handled by JavaScript to populate the second page.
I can already obtain the data via an ajax call and put it in a JSON array:
$.ajax({
type: "POST",
url: get_data_from_database_url,
async:false,
data: params,
success: function(json)
{
json_send_my_data(json);
}
});
function json_send_my_data(json)
{
//pass the json object to the other page and load it
}
I assume that on the second page, a "document ready" JavaScript function can easily handle the capture of the passed JSON object with all the data. The best way to test that it works is for me to use alert("My data: " + json.my_data.first_name); within the document ready function to see if the JSON object has been properly passed.
I simply don't know a trusted true way to do this. I have read the forums and I know the basics of using window.location.url to load the second page, but passing the data is another story altogether.
session cookie may solve your problem.
On the second page you can print directly within the cookies with Server-Script tag or site document.cookie
And in the following section converting Cookies in Json again
How about?
Warning: This will only work for single-page-templates, where each pseudo-page has it's own HTML document.
You can pass data between pages by using the $.mobile.changePage() function manually instead of letting jQuery Mobile call it for your links:
$(document).delegate('.ui-page', 'pageinit', function () {
$(this).find('a').bind('click', function () {
$.mobile.changePage(this.href, {
reloadPage : true,
type : 'post',
data : { myKey : 'myVal' }
});
return false;
});
});
Here is the documentation for this: http://jquerymobile.com/demos/1.1.1/docs/api/methods.html
You can simply store your data in a variable for the next page as well. This is possible because jQuery Mobile pages exist in the same DOM since they are brought into the DOM via AJAX. Here is an answer I posted about this not too long ago: jQuery Moblie: passing parameters and dynamically load the content of a page
Disclaimer: This is terrible, but here goes:
First, you will need this function (I coded this a while back). Details here: http://refactor.blog.com/2012/07/13/porting-javas-getparametermap-functionality-to-pure-javascript/
It converts request parameters to a json representation.
function getParameterMap () {
if (window.location.href.indexOf('?') === (-1)) {
return {};
}
var qparts = window.location.href.split('?')[1].split('&'),
qmap = {};
qparts.map(function (part) {
var kvPair = part.split('='),
key = decodeURIComponent(kvPair[0]),
value = kvPair[1];
//handle params that lack a value: e.g. &delayed=
qmap[key] = (!value) ? '' : decodeURIComponent(value);
});
return qmap;
}
Next, inside your success handler function:
success: function(json) {
//please really convert the server response to a json
//I don't see you instructing jQuery to do that yet!
//handleAs: 'json'
var qstring = '?';
for(key in json) {
qstring += '&' + key + '=' + json[key];
qstring = qstring.substr(1); //removing the first redundant &
}
var urlTarget = 'abc.html';
var urlTargetWithParams = urlTarget + qstring;
//will go to abc.html?key1=value1&key2=value2&key2=value2...
window.location.href = urlTargetWithParams;
}
On the next page, call getParameterMap.
var jsonRebuilt = getParameterMap();
//use jsonRebuilt
Hope this helps (some extra statements are there to make things very obvious). (And remember, this is most likely a wrong way of doing it, as people have pointed out).
Here is my post about communicating between two html pages, it is pure javascript and it uses cookies:
Javascript communication between browser tabs/windows
you could reuse the code there to send messages from one page to another.
The code uses polling to get the data, you could set the polling time for your needs.
You have two options I think.
1) Use cookies - But they have size limitations.
2) Use HTML5 web storage.
The next most secure, reliable and feasible way is to use server side code.