Jquery Tabs MVC 4 - Redirect to to tab from controller - asp.net-mvc-4

I have the following code where 'SelectedTabToFind' is set in the controller. This is used for validation, so that the correct tab is displayed.
$("#tabs").tabs(
{
active: $("#SelectedTabToFind").val(),
cache: false
});
<div id="tabs">
<ul>
<li>View</li>
<li>Update</li>
<li>Validate</li>
<li>Notes</li>
</ul>
<div id="tabs-1">
#Html.Partial("View",Model)
</div>
<div id="tabs-2">
#Html.Partial("Update",Model)
</div>
<div id="tabs-3">
#Html.Partial("Validate",Model.ValidateModel)
</div>
<div id="tabs-4">
#Html.Partial("Notes", Model)
</div>
View Tab - Displays Information
Update Tab - Can update information on tab
Validate Tab - Can update information on tab
Notes Tab - Displays a list of information with separate page outwith tabs to add/update a note
The validation works and displays correctly for Update and Validate tabs. The redirect does not work when I add/update a note as it uses a separate page outwith the tabs.
I have used the following code before to redirect to a tab
return Redirect(Url.Action("View", new { id = note.Id }) + "#tabs-4");
and this does not work with the above code
If I comment out 'active' it works correctly
$("#tabs").tabs(
{
//active: $("#SelectedTabToFind").val(),
cache: false
});
How do I redirect to the correct tab but keep active option for validation?

When you redirectto a tab, that tab becomes automatically active. You cannot do something and its contrary!
From jquery tabs doc
active
Type: Boolean or Integer
Default: 0
Which panel is currently open.
Multiple types supported:
Boolean: Setting active to false will collapse all panels. This requires the collapsible option to be true.
Integer: The zero-based index of the panel that is active (open). A negative value selects panels going backward from the last panel.

With the help of JQuery UI tabs: How do I navigate directly to a tab from another page?
The correct tab is displayed when validating a form and the redirect from another page works as well.
View Page
if (document.location.hash != '')
{
var tabSelect = document.location.hash.substr(1, document.location.hash.length);
//Used to return to tab using return Redirect(Url.Action("View", new { id = note.Id }) + "#4");
$("#tabs").tabs(
{
active: tabSelect,
cache: false
});
}
else
{
$("#tabs").tabs(
{
//Used to return to tab using return ViewModel.SelectedTab = 2;
active: $("#SelectedTabToFind").val(),
cache: false
});
}
Used for note section in controller
return Redirect(Url.Action("View", new { id = note.Id}) + "#4");
Used for Update and Validate section in controller
ViewModel.SelectedTab = 2;

Related

In Razor Pages, how can I preserve the state of a checkbox which is not part of a form?

I have page that has checkbox that is used to expand/collapse some part of the page. This is client-side logic done in JavaScript.
I want to preserve the state of this checkbox for this particular page. Can Razor Pages do this automatically?
I tried by adding bool property with [BindProperty(SupportsGet = true)] in PageModel but it doesn't work - when I check the checkbox and reload (HTTP GET) the checkbox is always false.
Guessing that this toggle feature is user-specific, and that you want to persist their choice over a number of HTTP requests, I recommend setting a cookie using client-side code, which is user- or more accurately device-specific and can persist for as long as you need, and can be read on the server too.
https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie
https://www.learnrazorpages.com/razor-pages/cookies
I want to preserve the state of this checkbox for this particular page. Can Razor Pages do this automatically?
No, since you don't send it to the backend it will not show it.
As Mike said, it better we could store it inside the client cookie or storage.
More details, you could refer to below codes:
<p>
<input type="checkbox" id="cbox1" checked="checked">
<label >This is the first checkbox</label>
</p>
#section scripts{
<script>
$(function(){
var status = getValue();
if(status === "true"){
$("#cbox1").attr("checked","checked");
}else{
$("#cbox1").removeAttr("checked");
}
})
$("#cbox1").click(function(){
var re = $("#cbox1").is(":checked")
alert(re);
createItem(re);
});
function createItem(value) {
localStorage.setItem('status', value);
}
function getValue() {
return localStorage.getItem('status');
} // Gets the value of 'nameOfItem' and returns it
console.log(getValue()); //'value';
</script>
}

PrimeNg TabView with ConfirmDialog not working

I'm trying to use PrimeNg TabView component along with confirmDialog unsuccessfully
I am able to show this confirm dialog but it appears after user switch to target tab panel which is wrong.
<p-tabView (onChange)="handleChange($event)" [(activeIndex)]="index">...</p-tabView>
handleChange(e) {
this.confirmationService.confirm({
message: 'There are unsaved changes, do you want to proceed?',
accept: () => {
this.index = e.index;
},
reject:() =>{ }
});
}
Do you have an idea on how to prevent or allow tab change using confirm dialog ?
Thanks
there is no official way to prevent change to another tab by press on that tab , but 😅 there is a work around it first we need to prevent the tab change by tab click,
1️⃣ we need to set the header by ng-template or it called a custom header
template
<p-tabPanel >
<ng-template pTemplate="header">
<div (click)="handleChange($event,0)">
Godfather I
</div>
</ng-template>
.....
</p-tabPanel>
2️⃣ we bind a click event to the new header text and by using mouse event stopPropagation method we can prevent the change 👌,now we can control the change by confirm result but you need to pass the current tab index, that why I add another parameter to handleChange
component
handleChange(e:MouseEvent,tabIndex:number) {
e.stopPropagation();
if (this.index == tabIndex){
return;
}
// console.log(tabIndex)
this.confirmationService.confirm({
message: "There are unsaved changes, do you want to proceed?",
accept: () => {
this.index = tabIndex;
},
reject: () => {}
});
}
the if block if (this.index == tabIndex){return;} use to prevent showing the confirm dialog if we click on the same active tab again
demo 🚀🚀

In Vue, how to get the content of a textarea?

I want to keep the value of a variable identical with the content of a textarea.
I don't want to use v-bind or v-model, because I have already bound the textarea with another value.
This is a notebook app, and the textarea is used to display the content of a note, so it has been bound using v-bind with a note object, like
<textarea cols="30" rows="3" v-bind:value="note"></textarea>
Now, I want to add the "edit note" functionality. So when the content of the textarea changes, I want to store its value into a variable, and when the "submit" button is clicked, I pass the value of the variable, which contains the new content of the note, to backend to update the note.
My question is, how to store the textarea's content into the variable after each time the content changes?
I think I cannot use v-model because this way the note will be changed right after the content of the textarea is modified (though not sent to backend), but this is not what I want. What I want is the note to be changed only after the "submit" button is clicked. Thus, I cannot use v-model
Should I use v-on:change? If so, how to get the content of the textarea?
Like,
<textarea v-on:change="updateTheVariable(I need to get the content of the textarea here)"> ... </textarea>
methods: {
updateTheVariable(content of the textarea) {
this.variable = content of the textarea
}
}
Thanks
I'm assuming this thing only shows up when you click some kind of edit button which is why you don't want to alter note so try something like this instead
<button type="button" v-if="!editMode" #click="editNote">Edit</button>
<form v-if="editMode" #submit="handleSubmit">
<fieldset :disabled="saving">
<textarea v-model="editingNote"></textarea>
<button type="submit">Edit</button>
</fieldset>
</form>
export default {
data: () => ({
note: 'whatever', // maybe it's a prop, maybe assigned later, doesn't matter
editMode: false,
editingNote: null, // this will be used to bind the edited value
saving: false
}),
methods: {
editNote () {
this.editingNote = this.note
this.editMode = true
this.saving = false
},
async handleSubmit () {
this.saving = true // disables form inputs and buttons
await axios.post('/notes/update', { note: this.editingNote}) // just an example
this.note = this.editingNote // or maybe use data from the response ¯\_(ツ)_/¯
// or if it's a prop, this.$emit('updated', this.editingNote)
this.editMode = false
}
}
}
As #Phil indicated in a deleted post, the right way to do it is
<textarea #input="updateTheVariable($event.target.value)"></textarea>
.
.
.
methods:{
updateTheVariable(value){
this.variable = value
}
}

Response.Redirect not changing URL

After clicking an element on my webpage, I get the expected behavior from Response.Redirect in the trace, the break point on the expected page gets hit and proceeds to process normally. However when I'd expect the new page to be loaded, the display in the browser is not changed. It looks and behaves like the click brought you back to the same page.
I've moved the redirect call out of a try-catch block, and have tried different combinations of true/false as the second parameter with HttpContext...CompleteRequest()
What might prevent a page from being loaded after a call from Response.Redirect and the Page_Load sub completes?
Edit:
The site uses css and javascript to create a hoverable dropdown menu containing self referencing links, see below. I have tried using Chrome's dev tools to see what the network was processing. As far as I can tell from reading the Network Tab the click was creating the correct call; status 200, type xhr. xhr was the only thing that I found odd, but it looks like this is simply a reference to ajax? This leaves me in the same position. I am telling the site to redirect to new url, and I see the network take a request for that url, but the url in the address bar doesn't change; not the displayed page.
$(document).on('click','.navigation', function () {
loadItems($(this).attr('id'), $(this).attr('itemName'));
return false;
}
);
var loadItems = function (id, itemName) {
var editInfor =
{
"method": "getChildItems",
"id": id
};
$.ajax
(
{
type: "POST",
url: $.url,
dataType: "json",
data: JSON.stringify(editInfor),
success: function (jsonReply) {
$("#chkEnabled").attr('checked', jsonReply.enabled)
if (jsonReply.method == 'getChildItems') {
$("#childrens").html('');
var html = '<table>'
if (jsonReply.successfull) {
$.each(jsonReply.children, function (i, item) {
html += '<tr><td><span class="children">' + item.text + '</span></td><td><a class="moveItemUp btn" href="#" id="moveItemUp' + item.id + '">Move Up <i class="icon-circle-arrow-up"></i></a> <a class="moveItemDown btn" href="#" id="moveItemDown' + item.id + '">Move Down <i class="icon-circle-arrow-down"></i></a></td><td>Remove</td></tr>'
});
}
html += '</table>'
$($.childrens).html(html);
}
}
}
);
Please try this:
$.mobile.changePage( "/Exmaple.aspx", {
transition: "pop"
});

JQuery UI Tabs: nested Tabs, AJAX loading and Back button

I'm loading JQuery UI tabs using AJAX.
I have 3 levels of nested UI tabs:
vertical
horizontal
horizontal
Most of the stuff is only 2 levels deep but some are 3. The issue is the 3rd level. I followed this:
http://benalman.com/code/projects/jquery-bbq/examples/fragment-jquery-ui-tabs/
But it does not cover nesting of tabs.
The layout of the page is like this:
<script type="text/javascript">
var tabs;
var tab_a_selector;
var tab_a_vertical_selector;
$(function() {
$("#menuTabs").tabs({
ajaxOptions: {
cache: false
}
}).addClass("ui-tabs-vertical ui-helper-clearfix");
$("#menuTabs li").removeClass('ui-corner-top').addClass('ui-corner-left');
$(".ui-tabs-vertical .ui-tabs-nav").removeClass("ui-tabs-nav").addClass("ui-tabs-nav-vert")
$("#menuItem0").tabs();
$("#menuItem1").tabs();
//...
/* -- enables Back button for nested tabs -- */
// The "tab widgets" to handle.
tabs = $('.tabs');
// This selector will be reused when selecting actual tab widget A elements.
tab_a_selector = 'ul.ui-tabs-nav a';
tab_a_vertical_selector = 'ul.ui-tabs-nav-vert a';
// Enable tabs on all tab widgets. The `event` property must be overridden so
// that the tabs aren't changed on click, and any custom event name can be
// specified. Note that if you define a callback for the 'select' event, it
// will be executed for the selected tab whenever the hash changes.
tabs.tabs({ event: 'change' });
// Define our own click handler for the tabs, overriding the default.
tabs.find(tab_a_selector).click(function(){
var state = {};
// Get the id of this tab widget.
id = $(this).closest( '.tabs' ).attr( 'id' );
// Get the index of this tab.
idx = $(this).parent().prevAll().length;
// Set the new state
// This is done as below to remove any state from deeper levels of nested tabs.
state ['menuTabs'] = $.bbq.getState('menuTabs');
state[ id ] = idx;
$.bbq.pushState( state, 2 );
});
tabs.find(tab_a_vertical_selector).click(function(){
var state = {};
// Get the id of this tab widget.
id = $(this).closest( '.tabs' ).attr( 'id' );
// Get the index of this tab.
idx = $(this).parent().prevAll().length;
// Set the state!
state[ id ] = idx;
// 2 -> replaces old state with new state. meaning indexes of nested tabs are removed
$.bbq.pushState( state, 2 );
});
// Bind an event to window.onhashchange that, when the history state changes,
// iterates over all tab widgets, changing the current tab as necessary.
$(window).bind( 'hashchange', function(e) {
// Iterate over all tab widgets.
tabs.each(function(){
// Get the index for this tab widget from the hash, based on the
// appropriate id property. In jQuery 1.4, you should use e.getState()
// instead of $.bbq.getState(). The second, 'true' argument coerces the
// string value to a number.
var idx = $.bbq.getState( this.id, true ) || 0;
// Select the appropriate tab for this tab widget by triggering the custom
// event specified in the .tabs() init above (you could keep track of what
// tab each widget is on using .data, and only select a tab if it has
// changed).
$(this).find( tab_a_selector).eq( idx ).triggerHandler( 'change' );
$(this).find( tab_a_vertical_selector ).eq( idx ).triggerHandler( 'change' );
});
})
// Since the event is only triggered when the hash changes, we need to trigger
// the event now, to handle the hash the page may have loaded with.
$(window).trigger( 'hashchange' );
/* -- END enables Back button for nested tabs -- */
});
</script>
<div id="menuTabs" class="tabs">
<ul>
<li>menuItem0</li>
<li>menuItem1</li>
<li>menuItem2</li>
</ul>
<div id="menuItem0" class="tabs">
<ul>
<li>Intro</li>
</ul>
</div>
<div id="menuItem1" class="tabs">
<ul>
<li>Introduction</li>
<li>Guide</li>
<li>abc</li>
</ul>
</div>
<!--...-->
</div>
The 3rd level of tabs is in the above html pages, as example in abc.html:
<script type="text/javascript">
var rNumberTabs = $("#rNumber").tabs();
rNumberTabs.tabs({ event: 'change' });
rNumberTabs.find(tab_a_selector).click(function(){
var state = {};
// Get the id of this tab widget.
id = $(this).closest( '.tabs' ).attr( 'id' );
// Get the index of this tab.
idx = $(this).parent().prevAll().length;
// Set the state!
state[ id ] = idx;
$.bbq.pushState( state );
});
tabs = tabs.add(grNumberTabs);
// If this is triggered it leads to an infinte loop,
// if not, I can't even browse to any other tab than the first
// one on he third level, eg. it automatically jumps back
// to first one.
$(window).trigger( 'hashchange' );
</script>
<div id="rNumber" class="tabs">
<ul>
<li>Layout</li>
<li>Prefix</li>
</ul>
<div id="layout">
<!-- Content here -->
</div>
<div id="prefix">
<!-- Content here -->
</div>
</div>
Any ideas how I can solve?
So here my current solution. The issue of endless looping seems to be caused by the fact that when using AJAX loading of tabs, the tab is loaded again for every click on it. Since the tabs that contain a 3rd level of tabs also contain JavaScript (see question) re-loading such a tab leads to issues.
The solution is to cache the tabs:
$("#menuTabs").tabs({
cache: true,
ajaxOptions: {
cache: false
}
})
Note: You must set Ajax cache to false:
http://docs.jquery.com/UI/Tabs#option-cache
Same for the 3rd level of tabs. And here also remove the call to hashchange event.
var rNumberTabs = $("#rNumber").tabs({
cache: true,
ajaxOptions: {
cache: false
}
});
//snipped..
//$(window).trigger( 'hashchange' ); remove this line