jQuery $.get refreshing page instead of providing data - asp.net

I have written some code using jQuery to use Ajax to get data from another WebForm, and it works fine. I'm copying the code to another project, but it won't work properly. When a class member is clicked, it will give me the ProductID that I have concatenated onto the input ID, but it never alerts the data from the $.get. The test page (/Products/Ajax/Default.aspx) that I have set up simply returns the text "TESTING...". I installed Web Development Helper in IE, and it shows that the request is getting to the test page and that the status is 200 with my correct return text. However, jQuery refreshes my calling page before it will ever show me the data that I'm asking for. Below are the code snippets from my page. Please let me know if there are other code blocks that you need to see. Thank you!
<script type="text/javascript">
$(document).ready(function() {
$(".addtocart_a").click(function() {
var sProdIDFileID = $(this).attr("id");
var aProdIDFileID = sProdIDFileID.split("_");
var sProdID = aProdIDFileID[5];
// *** This alert shows fine -- ProdID: 7
alert("ProdID: " + sProdID);
$.get("/Products/Ajax/Default.aspx", { test: "yes" }, function(data) {
// *** This alert never gets displayed
alert("Data Loaded: " + data);
}, "text");
});
});
</script>
<input src="/images/add_to_cart.png" name="ctl00$ctl00$ContentPlaceHolder1$ContentPlaceHolder1$aAddToCart_7" type="image" id="ctl00_ctl00_ContentPlaceHolder1_ContentPlaceHolder1_aAddToCart_7" class="addtocart_a" />

The easiest way is to tell jQuery not to return anything.
$(".addtocart_a").click(function(e){
// REST OF FUNCTION
return false;
});
Good luck! If you need anything else let me know.

Related

grails controller/action/id automagically turning into controller/index

My problem is that the backend server (written in grails) is automatically converting my request URL to be a different URL. Specifically, it is changing it from /UXChallengeAwards/processSelectedNotifications to /UXChallengeAwards/index.
--
In a template gsp file, I have defined a button that makes a jQuery ajax call when clicked on:
<button class="blue-link"
onclick="jQuery.ajax({type:'POST',
data:jQuery(this).parents('.multiSelectForm').serialize(),
url: '/ici/UXChallengeAwards/processSelectedNotifications/${challenge.id}',
success:function(data,textStatus){},
error:function(xhr,textStatus,errorThrown){}
})" >
The method UXChallengeAwardsController.processSelectedNotifications exists. It performs some work and then redirects to another action in the controller. In fact, this used to work. But somehow in the process of adding a second button I made a change which seems to have broken things.
When the button is now clicked, the request URL gets switched to /ici/UXChallengeAwards/index and a 404 is returned because index does not exist as an action in this controller.
I've googled, and the most common answer for when this happens is that a controller must return some results for the view. But I've seen plenty of examples of redirects in controllers, and I do not see what I am doing wrong. (I did try variants of rendering results, but with no success.)
Here is what my controller action looks like:
def processSelectedNotifications = {
def challenge
def checkboxes = params.list('selectCheckbox');
for (checkbox in checkboxes) {
// the checkbox contains the id of a ChallangeAward that should be published
ChallengeAwards challengeAwards = ChallengeAwards.get(checkbox.toInteger())
if (challengeAwards) {
// grab a challenge for use in the redirect, they are all the same
challenge=challengeAwards.challenge
publish(challengeAwards)
}
}
if (challenge) {
redirect action: 'challengeAwardsRemote', id: challenge.id
return
}
// render a failure message if we got here
render messageNS(code:"UX.ChallengeAwards.Publish.failure")
}
I would really appreciate any insights into what might be wrong, or how to go about tackling this issue. I've checked my UrlMappings, and this is the rule that should handle this controller/method request:
"/$controller/$action?/$id?"{ constraints {} }
Thank you very much!
I'm going to go ahead and answer my own question, in case it is helpful for other newbies.
It turns out that I was not getting an automatic redirect. Rather, I had an error in the button setup code, so that grails was using its default link behavior. (Which is to go to the controller that matches the view, and if no action is specified, use the index method.)
The code above was originally created using a remoteSubmit tag, but I found that the generated code did not support handling multiple forms on a single page very well. So, I copied that generated code and then tweaked it to handle the multiple forms. However, I wanted the styling to match up with what was already in place on the page, so I switched it to be a button. That's when things went awry.
Eventually, I ended up specifying an onClick function for the button, and then writing the ajax submit code in javascript. Which turned out to be much simpler.
Here is what the button specification ended up looking like:
<button type="submit" id="notifications" class="blue-link" >
<i class="fa fa-envelope-o"></i>
<g:messageNS
code="UX.DiscussionBoard.ChallengeAward.Button.notify" />
</button>
And the associated JavaScript:
jQuery(document).ready(function() {
var clkBtn = "";
jQuery('button[type="submit"]').click(function(evt) {
clkBtn = evt.target.id;
});
jQuery('.multiSelectForm').submit(function() {
var url = '/ici/UXChallengeAwards/processSelectedNotifications';
if (clkBtn == 'deletes') {
url ='/ici/UXChallengeAwards/processSelectedDeletes';
}
var errorTarget = jQuery(this).parents().find('.recipientMessage').val();
var requestData = jQuery(this).parents('.multiSelectForm').serialize();
var options = {
data : requestData,
type : 'POST',
url : url,
target : '#awardsTab',
error : function(data) {
jQuery('#' + errorTarget).html(data.responseText).show();
},
success : function(data) {
console.log("in success");
}
};
jQuery(this).ajaxSubmit(options);
return false;
});

Framework7 starter page "pageInit" NOT WORKING

anyone using framework7 to create mobile website? I found it was great and tried to learn it by myself, now I meet this problem, after I create my App, I want to do something on the starter page initialization, here, my starter page is index.html, and I set data-page="index", now I write this below:
$$(document).on('pageInit', function (e) {
var page = e.detail.page;
// in my browser console, no "index page" logged
if (page.name === 'index') {
console.log("index page");
});
// but I changed to any other page other than index, it works
// my browser logged "another page"
if(page.name === 'login') {
console.log('another page');
}
});
Anyone can help? Thank you so much.
I have also encountered with the same problem before.
PageInit event doesn't work for initial page, only for pages that you navigate to, it will only work for index page if you navigate to some other page and then go back to index page.
So I see two options here:
Just not use pageInit event for index page - make its initialization just once (just make sure you put this javascript after all its html is ready, or e.g. use jquery's on document ready event)
Leave index page empty initially and load it dynamically via Framework7's mainView.loadContent method, then pageInit event would work for it (that was a good option for me as I had different index page each time, and I already loaded all other pages dynamically from underscore templates)
I am facing same issue and tried all solutions in various forums.. nothing actually worked. But after lot of RnD i stumbled upon following solution ...
var $$ = Dom7;
$$(document).on('page:init', function (e) {
if(e.detail.page.name === "index"){
//do whatever.. remember "page" is now e.detail.page..
$$(e.detail.page.container).find('#latest').html("my html here..");
}
});
var me = new Framework7({material: true});
var mainview = me.addView('.view-main', {});
.... and whatever else JS here..
this works perfectly..
surprisingly you can use "me" before initializing it..
for using for first page u better use document ready event. and for reloading page event you better use Reinit event.
if jquery has used.
$(document).on('ready', function (e) {
// ... mainView.activePage.name = "index"
});
$(document).on('pageReinit', function (e) {
//... this event occur on reloading anypage.
});

Bootboxjs: how to render a Meteor template as dialog body

I have the following template:
<template name="modalTest">
{{session "modalTestNumber"}} <button id="modalTestIncrement">Increment</button>
</template>
That session helper simply is a go-between with the Session object. I have that modalTestNumber initialized to 0.
I want this template to be rendered, with all of it's reactivity, into a bootbox modal dialog. I have the following event handler declared for this template:
Template.modalTest.events({
'click #modalTestIncrement': function(e, t) {
console.log('click');
Session.set('modalTestNumber', Session.get('modalTestNumber') + 1);
}
});
Here are all of the things I have tried, and what they result in:
bootbox.dialog({
message: Template.modalTest()
});
This renders the template, which appears more or less like 0 Increment (in a button). However, when I change the Session variable from the console, it doesn't change, and the event handler isn't called when I click the button (the console.log doesn't even happen).
message: Meteor.render(Template.modalTest())
message: Meteor.render(function() { return Template.modalTest(); })
These both do exactly the same thing as the Template call by itself.
message: new Handlebars.SafeString(Template.modalTest())
This just renders the modal body as empty. The modal still pops up though.
message: Meteor.render(new Handlebars.SafeString(Template.modalTest()))
Exactly the same as the Template and pure Meteor.render calls; the template is there, but it has no reactivity or event response.
Is it maybe that I'm using this less packaging of bootstrap rather than a standard package?
How can I get this to render in appropriately reactive Meteor style?
Hacking into Bootbox?
I just tried hacked into the bootbox.js file itself to see if I could take over. I changed things so that at the bootbox.dialog({}) layer I would simply pass the name of the Template I wanted rendered:
// in bootbox.js::exports.dialog
console.log(options.message); // I'm passing the template name now, so this yields 'modalTest'
body.find(".bootbox-body").html(Meteor.render(Template[options.message]));
body.find(".bootbox-body").html(Meteor.render(function() { return Template[options.message](); }));
These two different versions (don't worry they're two different attempts, not at the same time) these both render the template non-reactively, just like they did before.
Will hacking into bootbox make any difference?
Thanks in advance!
I am giving an answer working with the current 0.9.3.1 version of Meteor.
If you want to render a template and keep reactivity, you have to :
Render template in a parent node
Have the parent already in the DOM
So this very short function is the answer to do that :
renderTmp = function (template, data) {
var node = document.createElement("div");
document.body.appendChild(node);
UI.renderWithData(template, data, node);
return node;
};
In your case, you would do :
bootbox.dialog({
message: renderTmp(Template.modalTest)
});
Answer for Meteor 1.0+:
Use Blaze.render or Blaze.renderWithData to render the template into the bootbox dialog after the bootbox dialog has been created.
function openMyDialog(fs){ // this can be tied to an event handler in another template
<! do some stuff here, like setting the data context !>
bootbox.dialog({
title: 'This will populate with content from the "myDialog" template',
message: "<div id='dialogNode'></div>",
buttons: {
do: {
label: "ok",
className: "btn btn-primary",
callback: function() {
<! take some actions !>
}
}
}
});
Blaze.render(Template.myDialog,$("#dialogNode")[0]);
};
This assumes you have a template defined:
<template name="myDialog">
Content for my dialog box
</template>
Template.myDialog is created for every template you're using.
$("#dialogNode")[0] selects the DOM node you setup in
message: "<div id='dialogNode'></div>"
Alternatively you can leave message blank and use $(".bootbox-body") to select the parent node.
As you can imagine, this also allows you to change the message section of a bootbox dialog dynamically.
Using the latest version of Meteor, here is a simple way to render a doc into a bootbox
let box = bootbox.dialog({title:'',message:''});
box.find('.bootbox-body').remove();
Blaze.renderWithData(template,MyCollection.findOne({_id}),box.find(".modal-body")[0]);
If you want the dialog to be reactive use
let box = bootbox.dialog({title:'',message:''});
box.find('.bootbox-body').remove();
Blaze.renderWithData(template,function() {return MyCollection.findOne({_id})},box.find(".modal-body")[0]);
In order to render Meteor templates programmatically while retaining their reactivity you'll want to use Meteor.render(). They address this issue in their docs under templates.
So for your handlers, etc. to work you'd use:
bootbox.dialog({
message: Meteor.render(function() { return Template.modalTest(); })
});
This was a major gotcha for me too!
I see that you were really close with the Meteor.render()'s. Let me know if it still doesn't work.
This works for Meteor 1.1.0.2
Assuming we have a template called changePassword that has two fields named oldPassword and newPassword, here's some code to pop up a dialog box using the template and then get the results.
bootbox.dialog({
title: 'Change Password',
message: '<span/>', // Message can't be empty, but we're going to replace the contents
buttons: {
success: {
label: 'Change',
className: 'btn-primary',
callback: function(event) {
var oldPassword = this.find('input[name=oldPassword]').val();
var newPassword = this.find('input[name=newPassword]').val();
console.log("Change password from " + oldPassword + " to " + newPassword);
return false; // Close the dialog
}
},
'Cancel': {
className: 'btn-default'
}
}
});
// .bootbox-body is the parent of the span, so we can replace the contents
// with our template
// Using UI.renderWithData means we can pass data in to the template too.
UI.insert(UI.renderWithData(Template.changePassword, {
name: "Harry"
}), $('.bootbox-body')[0]);

Trigger.io + Angular.js and updating a view after calling forge.ajax

Having a problem, and so far couldn't get any solutions for seemingly similar SO questions to work. Problem is this:
Using Trigger.io's forge.ajax, my Angular.js view is not updated after the data is returned. I realize this is because forge.ajax is an asychronous function, and the data is returned after the view has already been displayed. I have tried to update the view by using $rootScope.apply(), but it doesn't work for me as shown in the many examples I have seen.
See the Controller code below:
function OfferListCtrl($scope) {
$scope.offers = [];
$scope.fetchOffers = function(callback) {
$scope.offers = [];
var successCallback = function(odataResults) {
var rawJsonData = JSON.parse(odataResults);
var offers = rawJsonData.d;
callback(offers);
};
var errorCallback = function (error){
alert("Failure:" + error.message);
};
forge.request.ajax({
type: 'GET',
url: 'https://www.example.com/ApplicationData.svc/Offers',
accepts: 'application/json;odata=verbose',
username: 'username',
password: 'password',
success: successCallback,
error: errorCallback
});
};
$scope.fetchOffers(function(offers) {
$scope.offers = offers;
forge.logging.info($scope.offers);
});
}
All the code there works fine, and $scope.offers gets populated with the Offer data from the database. The logging function shows the data is correct, and in the correct format.
I have tried using $rootScope.apply() in the logical places (and some illogical ones), but cannot get the view to update. If you have any ideas how I can get this to work, I would greatly appreciate it.
Edit: Added HTML
The HTML is below. Note the button with ng-click="refresh()". This is a just a workaround so I can at least see the data. It calls a one-line refresh function that executes $rootScope.apply(), which does update the view.
<div ng-controller="OfferListCtrl">
<h1>Offers</h1>
<ul>
<li ng-repeat="offer in offers">
<p>Description: {{offer.Description}}<br />
Id: {{offer.Id}}<br />
Created On: {{offer.CreatedOn}}<br />
Published: {{offer.Published}}<br />
</p>
</li>
</ul>
<input type="button" ng-click="refresh()" value="Refresh to show data" />
</div>
You need to change
$scope.fetchOffers(function(offers) {
$scope.$apply(function(){
$scope.offers = offers;
});
forge.logging.info($scope.offers);
});
It is because all changes to the $scope has to be made within the angular scope, in this case since you are calling ajax request using forge the callback is not executing within the angular framework, that is why it is not working.
You can use $scope.$apply() in this case to execute the code within angular framework.
Look at the $apply() methods doc
$apply() is used to execute an expression in angular from outside of
the angular framework. (For example from browser DOM events,
setTimeout, XHR or third party libraries). Because we are calling into
the angular framework we need to perform proper scope life-cycle of
exception handling, executing watches.
do this
function MyController($scope, myService)
{
myService.fetchOffers(data){
//assign your data here something like below or whateever
$offers = data
$scope.$apply();
}
});
Thanks
Dhiraj
When I do that I have an error like : "$digest already in progress"...
I'm Working with $q...
Someone knwo how I can resolve this issue ?
yes, this is caused where ur data comes fast enough and angular has not finished his rendering so the update cant update "outside" angular yet.
so use events:
http://bresleveloper.blogspot.co.il/2013/08/angularjs-and-ajax-angular-is-not.html

jQuery load() with callback function wont capture click()

I am having no luck in getting a jqueryui dialog to ajax load a form, which inturn submits via ajax.
Everything works upto the point of catching the form that is being submited and instead sending it through an ajax call. Thus the form action is triggered and the browser redirected. The ajax call is never made.
My code is as follows
$(document).ready(function() {
$('.viewOrder').click(function() {
$('#displayOrder').load(this.href, [], function() {
console.log("landed here");
$('#blah').click(function() {
console.log("submiting the form via ajax");
$.ajax({
url: "/ajax/orderupdate",
type: "GET",
data: data,
cache: false,
//success
success: function (data) {
console.log("worked:");
}
});
return false;
});
});
return false;
});
});
.viewOrder is the a href that is ajax loaded. This works fine.
I have read many similar questions on here and it seems load() does not execute scripts that are embeded in the return html, but my return code is pure html no scripts. Any ideas?
IMHO you should try and capture the submit instead of the click, that way you prevent submits done by keyboard aswell, and it might even fix your problem.
The events are bound on page load. At page load the form you are binding the click event does not exist. I use the livequery plugin but they added Live to jquery 4 which you can also use(i had some issues with IE so i went back to livequery)
So load livequery with your scripts http://docs.jquery.com/Plugins/livequery
and change
$('#orderUpdate').submit(function() {
to
$("#orderUpdate").livequery("submit", function() {

Resources