I have a scenario where I’m using Ajax.ActionLink() to call and load a child view in a parent view. I have a button on the child view that calls another child view. I would like for this child view to also show on the parent view.
I could load the child view into the calling child view if I use Ajax.ActionLink and it would look as if it’s in the parent view which is fine but the button offers me more benefits including sending stuff in the beginform and checking the field before submitting.
When the user clicks on the button it sends selected data from two drowdown lists as well as other data in BeginForm like:
#using (Html.BeginForm("Action", "Controller", new { courseID = 1001 }, FormMethod.Post, new { #id = "formName", #name = "formName" }))
However when the view returns it opens in a new window not in the parent view or the child view that called it.
How can I get the partial view to show in the child view that calls it or on the parent. Meaning parent calls child A and child A calls child B.
Reason #2,343,657 why I despise the Ajax.* family of helpers. They hide functionality, such that when something doesn't work as you expect, you don't know why. Write your own AJAX; you'll never be sorry you did.
Anyways, your problem here is that Ajax.ActionLink writes JavaScript to the page that wires all this functionality up for you. You didn't write that JavaScript (and apparently didn't even know it was there), but it was there, nonetheless.
Now that you've switched to using Html.BeginForm, that JavaScript has gone away, leaving nothing but a standard HTML form, that causes a page reload on submit. If you want the same functionality, you could use Ajax.BeginForm instead. But, before you run off and do that, take the opportunity to improve your code and write the JavaScript yourself. Then, things are very explicit, and you (or another developer) never have to wonder how it works, because it's right there.
All you need to do is attach a handler to the form's submit event, serialize the form, then post it over AJAX, and then do something with the response. I'm going to use jQuery for this example because 1) AJAX is one of those things you should use some sort of framework for to avoid a bunch of repetitive boilerplate code and 2) since it comes with an MVC project by default, there's a fair chance you already have to there and available to use.
$(document).ready(function () {
$('#YourForm').on('submit', function (e) {
e.preventDefault();
$.post('/url/to/post/to', $(this).serializeArray(), function (result) {
// do something with `result`
// For example, if `result` is a string of HTML, you can just
// write it out to some element:
$('#ResultDiv').html(result);
});
});
});
Related
I have two UI5 XML views and the navigation has been implemented between both the views. Whenever I visit the second view, I manipulate the HTML DOM (using jQuery and CSS) to do some look and feel related changes which is not readily available in UI5 by default.
My issue is: When I wrote jQuery code to manipulate DOM in (route)patternMatched handler of second view, it is not working as DOM does not exist at that point. When I put the jQuery code in onAfterRendering() of second view, it gets executed only during first visit so not giving the desired result during 2nd visit onwards.
Can you tell me how to get rid of this issue or what design change I should make here?
Also, do we have any setting in UI5 by which onAfterRendering() will be called every time when I navigate to a view?
You can use the onBeforeShow method to do the manipulations required by you.
The onBeforeShow will be called every time the view is about to be shown to the screen.
But first you have to attach the event to the view in onInit.
Code:
onInit : function () {
this.getView().addEventDelegate({
onBeforeShow : jQuery.proxy(function(evt) {
this.onBeforeShow(evt);
}, this)
});
},
onBeforeShow: function() {
console.log('called from on Before show');
// DO manipulation here
}
If, you still don't find the DOM elements in this event handler, remember onBeforeShow has a sister: onAfterShow which will be called after the view is shown on screen.
API Link : NavContainerChild
Title is probably a little messy. Basically what I'm trying to do is to create a custom function that will modify an object properties, then return that object, and then call a function.
A little background on what I'm doing : Trying my best with the Zendesk API to use a web widget on my webpage. Basically this web widget is configured to be a HelpCenter on startup, which then shows a button for either live chat or email, depending on the state. The main property in question here is called 'suppress' which disables one of the widget pages (chat, email & helpCenter). And my goal is to make that custom function 'suppress' 2 of the 3 widget pages so it only shows one. Then a API func called zE.activate() would open up the widget.
I know this is a lot of text, let me show you the code I've got so far :
<script>
function setChatPopOutProps(window) {
window.zESettings = {
webWidget: {
contactForm: {
suppress: true
},
helpCenter: {
suppress: true
}
}
};
return window.zESettings;
};
function chatPopOut() {
setChatPopOutProps(window);
zE.activate();
};
</script>
Now when I click on the button that has chatPopOut() assigned, the zE.activate() works since it opens up the widget, but basically the setChatPopOutProps(window) didn't seem to work.
I also tried the following :
Not returning window or window.zESettings
Putting everything under a single function by putting zE.activate() at the end of zESettings or just after the return window or window.zESettings
If you need to see the widget in action to have an idea, you can see it right here. Click on the green button on the bottom right, type anything, and you'll see the contact form button pop up. This button changes for a chat button when a live chat agent is available.
Now I know this is something that I should normally work out with Zendesk directly, which I tried, but they told me that there's nothing that can do what I'm trying to accomplish, but I really feel like this has something to do with the way I'm doing things in javascript and not the way the API is built..
Does anyone have an idea ? I would really appreciate it.
P.S. This is my 2nd post, so I apologize in advance for mistakes I probably made in this question.
Sadly, it turns out that what you are trying to accomplish just isn't possible. As the zE.settings get applied when the widget is first initialized, so there is no way to dynamically alter the widget settings without doing an action such as refreshing the page and re-initializing the widget. As far I can see from your code, I dont think you want to refresh the page everytime, and reinitialize the widget just to apply those settings that you listed above.
Is there a way to re-execute JS without refreshing a page?
Say if I have a parent page and an inside page. When the inside page gets called, it gets called via ajax, replacing the content of the parent page. When user clicks back, I would like to navigate them back to the parent page without having to reload the page. But, the parent page UI relies on javascript so after they click back, I would like to re-execute the parent page's javascript. Is this possible?
Edit: Here is some code. I wrap my code in a function but where and how would you call this function?
function executeGlobJs() {
alert("js reload success");
}
You could use the html5 history-api:
In your click-handler you'll call the pushState-method, stat stores the current state for later reuse:
$(document).on('click', 'a.link', function () {
// some ajax magic here to load the page content
// plus something that replaces the content...
// execute your custom javascript stuff that should be called again
executeGlobJs()
// replace the browser-url to the new url
// maybe a link where the user has clicked
history.pushState(data, title, url);
})
...later if the user browses back:
$(window).on('popstate', function () {
// the user has navigated back,
// load the content again (either via ajax or from an cache-object)
// execute your custom stuff here...
executeGlobJs()
})
This is a pretty simple example and of course not perfect!
You should read more about it here:
https://css-tricks.com/using-the-html5-history-api/
https://developer.mozilla.org/en-US/docs/Web/API/History_API
For the ajax and DOM-related parts, you should need to learn a bit about jQuery http://api.jquery.com/jquery.ajax/. (It's all about the magic dollar sign)
Another option would be the hashchange-event, if you've to support older browsers...
You can encapsulate all your javascript into a function, and call this function on page load.
And eventually this will give you control of re-executing entire javascript without reloading the page.
This is common practise when you use any concat utility (eg. Gulp)
If you want to reload the script files as if it would be on a page reload, habe a look at this.
For all other script functions needed, just create a wrapper function as #s4n989 and #Rudolf Manusadzhyan wrote it. Then execute that function when you need to reinit your page.
I'm having the same problem I don't use jquery.
I don't have a solution yet. I think that your problem is that it doesn't read all the document.getelements after you add content, so my idea is to put all the element declarations in a function. And than after the ajax call ends to call the function to get all the elements again.
So it might be something like that
Func getElems(){
const elem= document.getelementsby...
Const elem.....
At the end of the js file make a call for
the function
getelems()
And than at the end of the event of the
ajax call. Just call the function again.
Sorry that is something that comes to my mind on the fly while reading and thinking on the problem i have too:).
Hope it helped I will try it too when I will be on the computer :)
I believe you are looking for a function called
.preventDefault();
Here's a link to better explain what it does - https://api.jquery.com/event.preventdefault/
Hope this helps!
EDIT:
By the way, if you want to execute the JS on back you can wrap the script inside of
$('.your-div').on('load', function(e) {
e.preventDefault();
//your JavaScript goes here
}
I'm using Parse JS in version 1.3.4 in a web app project
<script src="//www.parsecdn.com/js/parse-1.3.4.min.js"></script>
in one of my Views, I have this declaration:
var DrivesView = Parse.View.extend({
className :'backbone-container',
options: {},
events: {
"click i.map-view-open-button": "openMapViewInModal"
},
I wanted to put an event in a font awesome element, which has the class map-view-open-button. Parse is somehow different than Backbone on this...
This works pretty well like this:
reload the page
go to the view (by clicking on the menu)
click on the <i> element --> my function app.driveView.openMapViewInModal runs ok
I can open the modal (run the function) several times, it works.
BUT, if I click on the menu and go to another view, and then come back to app.driveView, then the event won't work. The function app.driveView.openMapViewInModal won't be called if I click on the <i> element.
The strange parte is that the event is still there in the view. I checked it with app.drivesView.events.
Do I need to somehow close the view when I leave (how?) and then render it again so that the events will be recreated?
This is what I tried so far. I thought that I can delete the event on the render function, and create it again. The problem is that the render function will be called only once (at the first visit). If I leave the view and come back, the render function won't be called, which is really strange since my router points to this function (where render is explicitly called):
drivesViewer: function(){
$('#app').html(this.driveView.render().el);
},
any ideas?
thanks.
I finally found a solution. It is really strange and against my expectation, but I'm not an expert, so my expectation is not really "valid".
here is what I did. On the viewer function I remove the view:
drivesViewer: function(){
this.drivesView.remove();
$('#app').html(this.driveView.render().el);
},
Then, inside the 'DrivesView' declaration, I removed the 'events' attribute and put this lines in the 'render' function:
this.undelegateEvents();
this.delegateEvents({"click i.map-view-open-button": "openMapViewInModal"})
now, each time the view is loaded, I remove the view, then I undelegate the envents (not sure if really needed), then set new events. It works.
Note: I think there is a difference between Backbone and Parse here, don't really know why. Any comment and discussion on this is appreciated.
I created some ajax paginated comments in WordPress. Unfortunately, if the user had clicked on the reply button and then goes about to click on another comment page, the Comment Form vanishes into thin air.
Anyways, simple question: Triggering the "Cancel Reply" function from my code each time the user clicks on a new ajax page would effectively solve the problem by causing the form to jump back to the original position.
How can I trigger cancel.onclick() from my own code easily? I was going to just duplicate commands and create a new function, but thought there might be an easier way to save a few bytes!
Here's the source code:
http://core.trac.wordpress.org/browser/trunk/wp-includes/js/comment-reply.dev.js
Try something like this:
$('#id_of_your_cancel_button').click();
// same thing as $('#id_of_your_cancel_button').trigger('click');
If the "cancel" logic is to be used in multiple contexts, perhaps it would be best if it lives in its own named function declaration, rather than the anonymous function expression as in your example. This would give you the option of doing something like this:
function myCancelCode(){
do_stuff();
}
Then in your addComment object:
cancel.onclick = myCancelCode;
and from anywhere else:
if( somethingHappens ){
myCancelCode();
}