jQuery Mobile navigate - Why is the state empty? - javascript

I'm using $.mobile.navigate("#test-page", {id:123}) to navigate to a secondary page.
The navigation from page to page works fine.... but the state is empty!
The docs clearly show that the state should contain all information I need when the navigation is performed.
This is the code I'm using:
$(window).on('navigate', function(event, data) {
console.log("navigated", data);
console.log(data.state.info);
console.log(data.state.direction);
console.log(data.state.url);
console.log(data.state.hash);
if (data.state.hash === "test-page") {
console.log("Test page", data.state.id);
}
});
Unfortunately data is passed as empty:
{
state:{}
}
The HTML is the following:
<div id="test-home" data-role="page">
<div data-role="header">
<h1>Test Home</h1>
</div>
<div data-role="content">
<div id="test-btn">
Click DIV for TEST page
</div>
</div>
<div data-role="footer">
</div>
</div>
<div id="test-page" data-role="page">
<div data-role="header">
<h1>Test Page</h1>
</div>
<div data-role="content">
Test page
</div>
</div>
Hope that someone can help. Thanks!

$.mobile.navigate and navigate event, are used to track URL history and pass/fetch data from URL. They work with browser's navigation (back / forward).
To pass data between pages dynamically within a webapp using internal navigation, use $.mobile.changePage.
Resources:
$.mobile.navigate()
Navigate
$.mobile.changePage()
Use the below code to pass data from page to another.
$.mobile.changePage('store.html', {
dataUrl: "store.html?id=123",
data: {
'id': '123'
},
reloadPage: true // force page to reload
});
To retrieve data
$('.selector').on('pagebeforeshow', function () {
var values = $(this).data("url").split("?")[1];
id = values.replace("id=", "");
console.log(id);
});

I know it is an old question, but #Omar's answer can be improved.
In fact, it is possible to use pagecontainerbeforehide, pagecontainerbeforeshow, pagecontainerhide, pagecontainershow, pagecontainertransition and pagecontainerchange (they are fired in this order) and inside the handler you can read the property history.state, that at that point is updated with the new state.
So, for example, you can write (to initialize things that need the page already formatted, e.g. Google Maps):
$(document).on("pagecontainershow", function(e, data) {
console.log("pagecontainershow: " + JSON.stringify(history.state));
});
This works in all cases: if you click on a link (with a hash, e.g. #user), if you navigate with the back and forward buttons, if you use $.mobile.navigate and also for window.history.back().
Moreover, you can pass complex data, not limited to the query string constraints.
Resources:
Pagecontainer
History

Related

Is there a way to identify which div users were viewing in a webpage and return to the same div after they resubmit the page?

use case:
I have a jsp page with multiple divs within an html form. The default view in (div1) must display when the page is first loaded while (div2 and div3 are hidden). On the initial page load each div contains different field data returned from a database query. A toggle function was implemented to show/hide divs and triggered by the user's selection view preference. After the form is submitted again by the user, jsp returns additional data to each div.
problem:
I need a way to have the web page identify which div the user was viewing and return to the same div in the page after they resubmit another database query bypassing the default view in (div 1).
Any help on this is greatly appreciated!
Below is an excerpt I am testing:
$(function() {
$('#div1').click(function() {
$('.div1').toggle(700);
if ($('.div1').is(':visible')) {
$('.div2').hide();
$('.div3').hide();
}
return false;
});
$('#div2').click(function() {
$('.div2').toggle(700);
if ($('.div2').is(':visible')) {
$('.div1').hide();
$('.div3').hide();
}
return false;
});
$('#div3').click(function() {
$('.div3').toggle(700);
if ($('.div3').is(':visible')) {
$('.div1').hide();
$('.div2').hide();
}
return false;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
<li>
Default Query View 1 Data
</li>
<li>
Query View 2 Data
</li>
<li>
Query View 3 Data
</li>
</nav>
<body>
<form id="jdform" name="jdform" method="post" action="testDivToggle.html">
<div id="div1" class="div1" style="display: block;">
<p>Default Data for View 1 query: field1,field2</p>
</div>
<div id="div2" class="div2" style="display: none;">
<p>Queried Data from View 2 query: field3,field4,field5</p>
</div>
<div id="div3" class="div3" style="display: none;">
<p>Queried Data from View 3 query: field6,field7</p>
</div>
<input type="submit" name="submit" value="submit" />
</form>
</body>
If you want to keep it simple, just save the div number in a cookie when the user clicks/opens a div. Then when you reload the page, enable the div based on that cookie value. If you don't set an expiration, the cookie will go away when the user closes their browser, which I assume should be fine in your case. Do something like this in each of your click functions:
$('#div1').click(function() {
$('.div1').toggle(700);
if ($('.div1').is(':visible')) {
document.cookie="divnum=1";
$('.div2').hide();
$('.div3').hide();
}
return false;
});
Then just check to see if there's a 'divnum' cookie when you load the page, and if so, open that div instead of the default.
use session storage to set the div id (update it on clicking into each div) and then on page load check the value that is present in session storage and show just the div with that div id - or leave them all visible and scroll to it.
#jdform div{display:none}
$(document).ready(function(){
var activeDiv= sessionStorage.getItem('activeDiv');
if(activeDiv==null){activeDiv='div1'}
$('#'+activeDiv).css('display','block');
})
$('div').click(function(){
var activeDiv=$(this).attr('id');
sessionStorage.setItem("activeDiv",activeDiv)
})

How to load a view when a button is pressed?

I have a list of buttons in my <div>, when the user click on a specific div, I want display a view of my controller, for example:
<div class="row">
<div id="booking" class="command-buttons tile col-xs-12 btn">
<h3 class="title">Book appointment</h3>
</div>
</div>
I want load the appointment booking page when my user click on booking div. For load a view I use this code:
$this->load->view('appointments/book', $view);
but how I can do this using js? Usually a call a function that contains the view load, but in this case I'm on js side.
probably something like that:
$('div#booking').on('click', function() {
$(this).load( "view.html");
});
you can find some details here http://api.jquery.com/load/
I'm not entirely sure, but I think
echo $this->load->view('appointments/book', $view, true);
will return the html to your ajax success function and you can then easily inject it in the page.

Display alert message after page reload

I have to call $route.reload(); in controller 2 addData API call so that I can get the added data in my UI. But then the text 'Data added successfully' goes away due to page refresh.
controller 1:
$rootScope.$on('reloaded', function(event, data) {
$scope.$parent.alerts.length=0;
$scope.$parent.alerts.push({type: 'success',msg: 'Data added successfully'});
});
controller 2:
$scope.add = function() {
someAPIService.addData(JSON.stringify($scope.rows)).success(function(response) {
ngDialog.close('ngdialog1');
$route.reload();
$rootScope.$emit('reloaded', "true");
});
}
HTML Part:
<section>
<div ng-controller="controller3">
<alert ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)">{{alert.msg}}</alert>
</div>
<div class="row form-inline" ng-controller="controller2 as vm">
<!-- Table data with text fields-->
</div>
<script type="text/ng-template" id="addDataDialog">
<div id="frm" ng-controller="controller1" class="col-xm-6">
<div class="form-group">
<!-- Labels with text fields-->
</div>
<button class="ngdialog-button" ng-click="add()">Save</button>
</div>
</script>
</section>
NOTE: Both controllers are in the same JS file and they are used for the same HTML file.
As you want to only load the latest record list which is on server side. Then there is not need to use $route.reload(); after making post call. You need to only make ajax call to get the latest records list that will solve your problem. For making ajax you need to refer $http
$route.reload() is getting used only when you need to load
controller again with specified template in your $routeProvider when
condition
just a simple hint of an answer:
add a (specific) cookie (with javascript) before calling reload (use e.g Cookies lib),
read it on reload,
and then delete it
Also you may use local storage if it is available instead of a cookie using same steps:
add a specific entry in local storage, before calling reload
read it on reload
and then delete it
Another option to maintain state client-side is to use url parameters but these will not do for page reload

On toggle Hide/show

I have this code.
If a user press on lets say burger and add it into session basket. The reload of page doesn't open the current Window View(Toggle)
How can I make it open the current again on reload...
<script type="text/javascript">
function unhide(divID) {
var item = document.getElementById(divID);
if (item) {
item.className=(item.className=='hidden')?'unhidden':'hidden';
}
}
</script>
This is how to show/hide the text.
<div id="sandwich" class="hidden">
Here you go 1 </div>
<div id="burger" class="hidden">
Here you go 2 </div>
Things like this are not persistent across page reload / refresh.
There are two basic approaches to it:
Session cookie and session on server, communication via AJAX
Store all in a cookie
Both require some extra work, but it's unavoidable.
For the cookie part, there's a nice jQuery plugin called jquery.cookie.

angularjs bindings won't show unless i make a GET call

here is my situation:
I have an "edit" screen in my app. To load this screen, i am passing in an object through a window.postMessage event. I am listening for this postMessage event in my controller for the edit page and assigning the passed-in object to a property on my scope called "patient". Then, in the edit page markup, i am using ng-repeat to bind to an array on my "patient" object. The problem is, the page does not update to show the received data.
Here is what my event handler code looks like in my controller:
window.addEventListener("message", function(event) {
if (event.data.view === 'edit') {
$scope.patient = event.data.patient;
}
});
Here is what the markup looks like to bind to the patient object:
<div ng-repeat="dataItem in patient.fields | filter:{display:true}">
<div class="row" >
<div class="col-xs-12">
{{dataItem.displayName}}:
</div>
</div>
<div class="row" >
<div class="col-xs-12">
<input type="text" style="width: 100%;" ng-model="dataItem.value" /><br />
</div>
</div>
</div>
The data loads correctly and the $scope.patient property is getting fully populated, but the screen does not update. However, if I add a simple 'GET' call using RESTAngular, and don't even use the result of the call, the page updates correctly. Why is that and what can I do to get the page to update without the meaningless RESTAngular call? Here is the code that works with the RESTAngular call:
window.addEventListener("message", function(event) {
if (event.data.view === 'edit') {
patient = PatientRestangular.one('patients', event.data.patientId);
//this is a hack
//the data will not load on the edit screen without a call to 'get()'
patient.get().then(function(){
$scope.patient = event.data.patient;
});
}
});
Try $apply:
$scope.$apply(function(){
$scope.patient = event.data.patient;
});

Categories