PushPageModel not working on simple button in Xamarin - xamarin

Using the function below does not move the page to the desired view. The function is called from a Button Command
WeeklyJourneysCommand = new AsyncCommand(WeeklyJourneysAsync);
Which calls
async Task WeeklyJourneysAsync()
{
await base.CoreMethods.PushPageModel<EventListPageModel>(App.CurrentWeekNumber);
}

Sorted - multiple master detail pages causing issues

Related

Hide Testcafe Overlay

I'm trying to use testcafe to fill forms on a page.
When the form is filled, I'd like to be able to stop the test with the window still open so a human can review the form before clicking submit.
I can pause the test with t.debug() but this locks the page and shows the testcafe controls overlay at the bottom.
Is there a way I can remove this overlay and unlock the page?
I've tried using client functions to hide the element with javascript as follows:
test('test_1', async (t) => {
const hideOverlay = ClientFunction(function() {
const target = document.querySelector('#root-hammerhead-shadow-ui > div > div');
target.style.display = 'none';
return true;
})
await t.wait(5000);
setTimeout(async function() {
const res = await hideOverlay();
console.log('-------->', { res });
}, 6000);
await t.debug();
});
Since no code will be executed after debug is invoked, I thought I could use a settimeout to queue the call to the function that hides the overlay, so that it is queued and only executes after debug is called and the overlay is visible.
Didn't work though :( code didn't execute, got an unhandled promise rejection.
Could really use some help here, thanks :)
Yes, you can unlock the page by clicking the 'Unlock page' button in the footer as #VysakhMohan mentioned in the comment.
Please refer to the client-side debugging documentation for more details.

Ajaxinate Endless scolling has stopped product Quick View from working

I am using Shopify "Streamline Theme" with quick product view and I recently added infinite scroll to products on each collection using Ajaxinate.js.
When I open a collection page it loads with some products which is supposed to do, The products already there work fine with quick view and quick add to cart and also.
The Infinite scroll works fine and it loads new product fine but the problem is raised when the new products loaded through AJAX call doesn't have work with the quick view function.
I have tried to create a callback function to activate the quick view with no success, using the theme initialisation code with no success.
function callBack(){
theme.init();
theme.initQuickShop();
};
document.addEventListener("DOMContentLoaded", function() {
var endlessClick = new Ajaxinate({
method: "scroll",
loadingText: 'Loading...',
callback: callBack
});
});
Edit -------
My problem, is that when the page is loaded only the initial loaded products quickview elements are loaded in the DOM. When the scroll more button is clicked, the newly loaded products are loaded without their respective quickview elements. Hence why the quickview does't work for them. The theme.js file comes with this initialisation code:
theme.reinitProductGridItem = function($scope) {
if (AOS) {
AOS.refreshHard();
}
if (theme.settings.currenciesEnabled) {
theme.currencySwitcher.ajaxrefresh();
}
// Reload quick shop buttons
theme.initQuickShop(true);
// Refresh reviews app
if (window.SPR) {
SPR.initDomEls();SPR.loadBadges();
}
// Re-register product templates in quick view modals.
// Will not double-register.
sections.register('product-template', theme.Product, $scope);
// Re-hook up collapsible box triggers
theme.collapsibles.init();
};
I have tried to integrate this into a callback but no success, the quickview modal doesn't seem to load for the newly loaded products:
function callBack(){
ReloadSmartWishlist();
var $container = $('#CollectionSection');
theme.reinitProductGridItem($container);
// I have tried the following init qith no success:
// theme.init();
// theme.initQuickShop(true);
// theme.initQuickShop();
// sections.register('product-template', theme.Product, $container);
// AOS.refreshHard();
};
document.addEventListener("DOMContentLoaded", function() {
var endlessClick = new Ajaxinate({
method: "click",
loadingText: 'Loading...',
offset: 0,
callback: callBack
});
});
I am missing something but what? :/
Note for other things like loading products images with the callback and the wishlist app, it works as intended...
When you load elements via AJAX and if the events are not attached to a parent element that is not removed from the DOM, those elements will not have an attached event to them.
The term used here is event delegation.
Here is an example of non-delegated event:
document.querySelectorAll('a').addEventListener('click', function(){
// Do something
})
Since you are attaching the event to the existing "a" elements if you add new 'a' via AJAX those elements will not have the event since Javascript already attached all the events and it will not reattach them if you don't specifically recall them again.
Here is an example of a delegated event:
document.querySelector('body').addEventListener('click', function(target){
let target = event.target;
if (target.tagName === 'A'){
// Do something here
}
})
Where we attach the event to the body tag ( where it's a better idea to attach it to a closer none-modified parent element of the ajax items ) and once we click we check if our target tag is an "a" and do something then.
So long story short, you will need to delegate the quick cart link so that it works after you load the items via AJAX.
Drip is correct you need to delegate your event, but for people like me it's hard to completely understand how to do that.
I'm not sure how your quickview is structured, but if you open it with a .click function and can use jquery use the [.on() function][1].
For example: I use a quickview that opens on a button click. My button is attached to my product-grid-item.liquid with this bit of code:
<div class="quick-view-button">
<a class="quick-view" data-handle="{{ product.handle }}" href="javascript:void(0);">Quick View</a>
</div>
My quickview function originally looked like this:
function quickView() {
$(".quick-view").click(function () {
//all of the quickview code
What happens is exactly like you described. The event listeners only loaded on the first product load but nothing after an AJAX load.
Using jquery's .on() binds the event listener to the element meaning when it's loaded in later it'll still have the event. Here's an example of what my code looks like after using .on()
function quickView() {
$('body').on('click','.quick-view',function(){
I really hope this helps you or someone else with this problem.
[1]: http://api.jquery.com/on/

I am trying to run a task in my async method but it's giving me a ui thread error

Here's what I am trying to do:
public async void CreateListSectionAsync()
{
details.Children.Clear();
details.Children.Add(new MessageGridTemplate()
{
Label = "Information",
Text = "Fetching card details, please be patient"
});
await Task.Run(() =>
{
// modify the UI
details.Children.Clear();
});
}
But this gives a UI error. Is the way I am calling the task not correct?
ListViews or other views that highly modify the UI hate being on a separate thread. So when you call
await Task.Run(() =>
{
// modify the UI
details.Children.Clear();
});
the UI will exception because you are modifying the screen from a non-UI thread. Try calling the details.Children.Clear in a Device.BeginInvokeOnMainThread call.
Even just adding or removing a single element won't be happy on a separate thread/context.
You cannot modify UI elements from a background thread.
The appropriate mitigation is not Device.BeginInvokeOnMainThread. A more correct approach depends on what kind of UI updates you're doing:
To display the results of a background thread operation, use await.
To display progress or multiple results of a background thread operation, use Progress<T> / IProgress<T>.
To display updates as events are pushed to your app, use SynchronizationContext or IObservable<T>.ObserveOn.

LightSwitch Tabbed screen in Browse template

I have a screen where we have 4 tabs, each tab should be displayed as per the login priority.
Ex:Department,Role,Employee,Screen are the tabs.
Each tab is having buttons to add,edit,remove the data.
by default when i log with any user its going to the first tab, but not all the users are having the first tab as their requirement.
how can i resolve this to do it dynamically in html client application
As covered towards the end of the following LightSwitch Team blog post, you can programmatically change the tab by using the screen.showTab method:
Creating a wizard-like experience for HTML client (Andy Kung)
However, in order to use this showTab API command when your screen is loading, its use needs to be delayed until the screen has fully displayed. This can be achieved in your screen's created method by using a combination of the jQuery mobile pagechange event (as the LightSwitch HTML Client uses jQuery mobile) and a setTimeout with a zero timeout (to delay the showTab until the loading screen is rendered).
The following shows a brief example of how you can use this approach to dynamically set the initial screen tab:
myapp.BrowseScreen.created = function (screen) {
var initialTabName = localStorage.getItem("Rolename") + "Tab";
$(window).one("pagechange", function (e, data) {
setTimeout(function () {
screen.showTab(initialTabName);
});
});
};
Based on your earlier post it appears that you're using LocalStorage to track your logged in user and their role.
On this basis, the above example assumes that the user's role will be the factor dictating the tab they are shown when the screen loads (the screen is named BrowseScreen in the above example).
It also assumes that your tabs are named after each employee role (suffixed with the text 'Tab') e.g. a user who is assigned the role 'DepartmentManager' would be directed to a tab called 'DepartmentManagerTab'.
Whilst slightly more involved, if you'd prefer to avoid the pagechange and setTimeout it's possible to customise the LightSwitch library to introduce a new navigationComplete screen event. This new event is ideal for executing any operations dependent upon the screen having fully rendered (such as navigating to a different tab using the showTab function).
If you'd like to introduce this additional event, you'll need to reference the un-minified version of the LightSwitch library by making the following change in your HTML client's default.htm file (to remove the .min from the end of the library script reference):
<!--<script type="text/javascript" src="Scripts/msls-?.?.?.min.js"></script>-->
<script type="text/javascript" src="Scripts/msls-?.?.?.js"></script>
The question marks in the line above will relate to the version of LightSwitch you're using.
You'll then need to locate the section of code in your Scripts/msls-?.?.?.js file that declares the completeNavigation function and change it as follows:
function completeNavigation(targetUnit) {
msls_notify(msls_shell_NavigationComplete, { navigationUnit: targetUnit });
var screen = targetUnit.screen;
var intialNavigation = !screen.activeTab;
var selectedTab = targetUnit.__pageName;
if (screen.activeTab !== selectedTab) {
callNavigationUnitScreenFunction(targetUnit, "navigationComplete", [intialNavigation, selectedTab]);
screen.activeTab = selectedTab; // Set at the end of the process to allow the previous selection to be referenced (activeTab)
}
}
function callNavigationUnitScreenFunction(navigationUnit, functionName, additionalParameters) {
var screenObject = navigationUnit.screen;
var constructorName = "constructor";
var _ScreenType = screenObject[constructorName];
if (!!_ScreenType) {
var fn = _ScreenType[functionName];
if (!!fn) {
return fn.apply(null, [screenObject, navigationUnit].concat(additionalParameters));
}
}
}
You can then use this new event in your screens as follows:
myapp.BrowseScreen.navigationComplete = function (screen, navigationUnit, intialNavigation, selectedTab) {
if (intialNavigation) {
var initialTabName = localStorage.getItem("Rolename") + "Tab";
screen.showTab(initialTabName);
}
};
This event fires whenever a navigation event completes (including a change of tab) with the initialNavigation parameter being set to true upon the initial load of the screen and the selectedTab parameter reflecting the selected tab.
Although modification to the LightSwitch library aren't uncommon with some of the more seasoned LightSwitch developers, if you decide to go down this path you'll need to thoroughly test the change for any adverse side effects. Also, if you upgrade your version of LightSwitch, you'll need to repeat the library modification in the new version.

Kendo Grid - PopUp windows not being removed from the DOM

I have a kendo grid with a custom popup:
columns.Command(commands =>
{
commands.Edit();
}
.Editable(editing => editing.Mode(Kendo.Mvc.UI.GridEditMode.PopUp))
Each time I click the edit button the window pops up but when I close it the window is not removed from the DOM.
I saw this post: http://www.telerik.com/forums/popup-windows-do-not-get-removed-from-dom and Telerik says the issue has been fixed.
What are some things that would cause this behavior?
UPDATED
This grid is nested in a Kendo TabStrip if that helps. Other than that I don't see anything out of the ordinary. The popup is entirely managed by the grid.
UPDATED 2
So I got the un-minimized code for the grid (kendo.grid.min.js, version 2013.3.1119, starting at line 1172), slopped it into my project and modified just the following with the two log statements to verify that destroy is being bound and called:
_destroyEditable: function () {
var that = this;
var destroy = function () {
if (that.editable) {
// My edit
console.log("...destroy() called");
that._detachModelChange();
that.editable.destroy();
that.editable = null;
that._editContainer = null;
}
};
if (that.editable) {
if (that._editMode() === "popup") {
// My edit
console.log("Binding destroy() to 'deactivate'...");
that._editContainer.data("kendoWindow").bind("deactivate", destroy).close();
} else {
destroy();
}
}
},
Each time I click edit and then close the window I see the expected two messages yet the window is not removed. Here is a screenshot of the debugger:
The outlined windows are the dom elements generated.
After much trial and error and deep diving it turns out this problem has to do with our scripts in our site's layout. At some point whomever setup the kendo scripts put in not only the 'kendo.all.min.js' but right after it 'kendo.web.min.js', 'kendo.aspnetmvc.min.js' and then about 10 individual kendo.*.js including the grid.
After viewing this link:
http://docs.telerik.com/kendo-ui/getting-started/javascript-dependencies
I realized that the site is creating these objects multiple times. Removing the script references in accordance to the link above resolves the issue.

Resources