Showing an intro of React Native app only once? - ios

I already have a Model view in react native that can be accessed from a button in the settings, and I would like it to pop up the first time the app is used. In other words, I don't have any problems with the view itself, just the functionality.
I've considered user React-native-simple-store but it seems like there should be an easier way.
Thanks,
Eric

To pop-up the modal you will have to set its visible props:
<Modal visible={this.state.showModal} ...
If you save this value into AsyncStorage, or any database, like RealmDB or Sqlite, you can always read the value and then make modal show-up only once. Put it in componentDidMount :
const value = AsyncStorage.getItem('once');
if (value !== null) {
value.then((ret) => {
if (ret === null) {
// this is the first time
// show the modal
// save the value
AsyncStorage.setItem('once', 'yes');
this.setState({
showModal: true,
});
} else {
// this is the second time
// skip the modal
}
}).catch(err => alert(err.toString()));
}
In your modal:
<Modal visible={this.state.showModal} ...
In your constructor:
this.state = {showModal: false}

Related

Flipswitch in lightswitch is going in an infinite loop

I got this piece of code for rendering and using Flipswitch as a custom control in lightswitch application.
function createBooleanSwitch(element, contentItem, trueText, falseText, optionalWidth) {
var $defaultWidth = '5.4em';
var $defaultFalseText = 'False';
var $defaultTrueText = 'False';
var $selectElement = $('<select data-role="slider"></select>').appendTo($(element));
if (falseText != null) {
$('<option value="false">' + falseText + '</option>').appendTo($selectElement);
}
else {
$('<option value="false">' + $defaultFalseText + '</option>').appendTo($selectElement);
}
if (trueText != null) {
$('<option value="true">' + trueText + '</option>').appendTo($selectElement);
}
else {
$('<option value="true">' + $defaultTrueText + '</option>').appendTo($selectElement);
}
// Now, after jQueryMobile has had a chance to process the
// new DOM addition, perform our own post-processing:
$(element).one('slideinit', function () {
var $flipSwitch = $('select', $(element));
// Set the initial value (using helper function below):
setFlipSwitchValue(contentItem.value);
// If the content item changes (perhaps due to another control being
// bound to the same content item, or if a change occurs programmatically),
// update the visual representation of the control:
contentItem.dataBind('value', setFlipSwitchValue);
// Conversely, whenver the user adjusts the flip-switch visually,
// update the underlying content item:
$flipSwitch.change(function () {
contentItem.value = ($flipSwitch.val() === 'true');
});
// To set the width of the slider to something different than the default,
// need to adjust the *generated* div that gets created right next to
// the original select element. DOM Explorer (F12 tools) is a big help here.
if (optionalWidth != null) {
$('.ui-slider-switch', $(element)).css('width', optionalWidth);
}
else {
$('.ui-slider-switch', $(element)).css('width', defaultWidth);
}
//===============================================================//
// Helper function to set the value of the flip-switch
// (used both during initialization, and for data-binding)
function setFlipSwitchValue(value) {
$flipSwitch.val((value) ? 'true' : 'false');
// Having updated the DOM value, refresh the visual representation as well
// (required for a slider control, as per jQueryMobile's documentation)
$flipSwitch.slider(); // Initializes the slider
$flipSwitch.slider('refresh');
// Because the flip switch has no concept of a "null" value
// (or anything other than true/false), ensure that the
// contentItem's value is in sync with the visual representation
contentItem.value = ($flipSwitch.val() === 'true');
}
});
}
This piece of code works fine. It renders the flipswitch on the screen. I am showing the data in an Edit screen, which is coming in a popup. Problem arises when I open that popup which contains the flipswitch and without changing any data on UI, I just try to close that popup screen. The IE hangs and it gives error saying that long script is running. When I debug the createBoolenaSwitch function, I came to know that it is going in infinite loop inside the function called setFlipSwitchValue(value){}
Why is this function getting called and this is going in an infinite loop?

Anonymous callback function to JsObject doesn't update Dart Controller until after a user action

Given the dart code
class LandingController {
bool hideDiv = false;
void doit() {
new JsObject(context['loginControls']).callMethod('fadeLogin', [() {
print(hideDiv);
hideDiv = true;
print(hideDiv);
print("WTF");
}]);
}
}
which calls the JS:
var loginControls = function() {
this.fadeLogin = function(func) {
$('#landingHeader').animate({ opacity: 0 }, 500, func);
}
};
which should affect the view:
<button ng-click="doit();">Click</button>
<div id="landingHeader">Hide me after button click</div>
<div ng-if="ctrl.hideDiv == false"><img src="assets/img/ajax-loader-small.gif">Waiting for div to disappear...</div>
After a button click and a 500 millisecond delay I see in my console a "WTF" print correctly. The div, however, is still visible. Once a user action occurs, in my case a mouse click, the div magically disappears. It seems as though the controller's value is changed, but the browser doesn't receive the change to hide the div, as I've printed the controller's value in the anonymous callback.
There is a work around, but it involves setting Dart timer's to the same fade times that you use in the javascript after the JsObject call and setting your controller's values in those Timer callbacks - gross but it works.
I think you need to call scope.apply(). I think Angular just can't recognize the value change in hideDiv when doit() is called from another zone (like JS).
You usually don't need to call scope.apply() in Angular.dart but I think this is one of the exceptions.
Is the animate function the only reason you use jQuery? It might be easier to do this with Angular.darts animation features.

Can't open Telerik Kendo window twice

I have a Kendo window which is defined as follows:
With Html.Kendo().Window().Name("tranferwindow")
.Title("Select Transfer Destination")
.Content("")
.Resizable()
.Modal(True)
.Events(Function(events) events.Open("WindowToCenter"))
.Events(Function(events) events.Refresh("transferopen"))
.Draggable()
.Width(400)
.Visible(False)
.Render()
End With
The window is opened each time by using the refresh and passing a new URL.This is to allow dynamic data to be displayed dependent on what the user clicked on a grid.
function transferitem(e) {
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
wwindow.data("kendoWindow").open(); //Display waiting window while refresh happens
var twindow = $("#tranferwindow")
twindow.data("kendoWindow").refresh('/Home/TransferList?agentid=' + agentid + '&tenantid=' + tenantid + '&SessionID=' + dataItem.MediaID);
}
The Window is opened at the end of the refresh event to make sure the user doesn't see the previous content.
function transferopen() {
wwindow.data("kendoWindow").close(); //Close the 'wait' window
var twindow = $("#tranferwindow")
twindow.data("kendoWindow").center().open();
}
This all works well and the window can be closed and reopened as often as I like.
However I needed to access the resize event of the window from within the Partial View to resize the Grid which is inside the window. To achieve this I added the following to the partial view that is returned from the url.
$("#tranferwindow").kendoWindow({
resize: function (e) {
// resizeGrid();
}
});
Adding this event mapping causes the issue where I cannot open the Window more than once.
I assume I need to 'unregister' for the event somehow before closing?
Found a solution: much cleaner and no VB Razor needed :)
I changed the approach to create a new window each time I wanted to display one.
I created a div to hold the Window.
<div id="windowcontainer"></div>
Then when the user selected a command on the grid , I create the whole window appending it to the div. The key here is the this.destroy in the deactivate event.
function transferitem(e) {
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
$("#windowcontainer").append("<div id='tranferwindow'></div>");
var mywindow = $("#tranferwindow")
.kendoWindow({
width: "400px",
title: "Select Transfer Destination",
visible: false,
content: '/Home/TransferList?agentid=' + agentid + '&tenantid=' + tenantid + '&SessionID=' + dataItem.MediaID,
deactivate: function () {
this.destroy();
},
open: WindowToCenter,
refresh:transferopen
}).data("kendoWindow");
mywindow.refresh();
}
Then on the refresh function
function transferopen() {
var twindow = $("#tranferwindow")
twindow.data("kendoWindow").center().open();
}
Now I can have the event binding inside the Partial View which works fine and the window can be re opened as many times as I want. :)
Update: Adding the event binding inside the Partial View stops 'Modal' from working. Working on trying to fix this...

jQuery UI Accordion - does refresh method overwrites initialisation settings?

Currently I am working on a project for which I use the jQuery UI Accordion.
Therefore I initialise the accordion on an element by doing
<div id="accordion"></div>
$('#accordion').accordion({
collapsible: true,
active: false,
heightStyle: "content"
});
After init the accordion I append some data coming from an AJAX request. (depends on user interaction)
In a simplified jsfiddle - which does exact the same thing as the ajax call - you can see how this looks like.
So far it seems to be working quite well but there is one problem I face.
In my initialisation I say that I want all panels to be closed but after calling refresh on the accordion everything of those settings seems to be gone and one panel opens.
Note that I implemented jQuery UI v1.10.2 in my fiddle. Update notes say
The refresh method will now recognize panels that have been added or removed. This brings accordion in line with tabs and other widgets that parse the markup to find changes.
Well it does but why has it to "overwrite" the settings I defined for this accordion?
I also thought about the possibility that it might be wrong to create the accordion on an empty <div> so I tested it with a given entry and added some elements afterwards.
But the jsfiddle shows exactly the same results.
In a recent SO thread I found someone who basically does the same thing as I do but in his jsfiddle he faces the same "issue".
He adds a new panel and the first panel opens after the refresh.
My current solution for this issue is to destroy the accordion and recreate it each time there's new content for it.
But this seems quite rough to me and I thought the refresh method solves the need to destroy the accordion each time new content gets applied.
See the last jsfiddle
$(document).ready(function () {
//variable to show "new" content gets appended correctly
var foo = 1;
$('#clickMe').on('click', function () {
var data = '';
for (var i = 0; i < 3; i++) {
data += '<h3>title' + foo + '</h3><div>content</div>';
foo++;
}
if ($('#accordion').hasClass('ui-accordion')) {
$('#accordion').accordion('destroy');
}
$('#accordion').empty().append(data).accordion({
collapsible: true,
active: false,
heightStyle: "content"
});
});
});
Unfortunately it is not an option for me to change the content of the given 3 entries because the amount of panels varies.
So my questions are the one in the title and if this behaviour is wanted like that or if anybody faces the same problem?
For the explanation of this behaviour, have a look in the refresh() method of the jquery-ui accordion widget, the problem you are facing is at line 10 :
refresh: function() {
var options = this.options;
this._processPanels();
// was collapsed or no panel
if ((options.active === false && options.collapsible === true) || !this.headers.length) {
options.active = false;
this.active = $();
// active false only when collapsible is true
} if (options.active === false) {
this._activate(0); // <-- YOUR PROBLEM IS HERE
// was active, but active panel is gone
} else if (this.active.length && !$.contains(this.element[0], this.active[0])) {
// all remaining panel are disabled
if (this.headers.length === this.headers.find(".ui-state-disabled").length) {
options.active = false;
this.active = $();
// activate previous panel
} else {
this._activate(Math.max(0, options.active - 1));
}
// was active, active panel still exists
} else {
// make sure active index is correct
options.active = this.headers.index(this.active);
}
this._destroyIcons();
this._refresh();
}

Monotouch.Dialog - How to push a view from an Element

It seems like this should be very easy, but I'm missing something. I have a custom Element:
public class PostSummaryElement:StyledMultilineElement,IElementSizing
When the element's accessory is clicked on, I want to push a view onto the stack. I.e. something like this:
this.AccessoryTapped += () => {
Console.WriteLine ("Tapped");
if (MyParent != null) {
MyParent.PresentViewController(new MyDemoController("Details"),false,null);
}
};
Where MyDemoController's gui is created with monotouch.dialog.
I'm just trying to break up the gui into Views and Controlls, where a control can push a view onto the stack, wiat for something to happen, and then the user navigates back to the previous view wich contains the control.
Any thought?
Thanks.
I'd recommend you not to hardcode behavior in AccessoryTapped method, because the day when you'll want to use that component in another place of your project is very close. And probably in nearest future you'll need some another behavior or for example it will be another project without MyDemoController at all.
So I propose you to create the following property:
public Action accessoryTapped;
in your element and its view, and then modify your AccessoryTapped is that way:
this.AccessoryTapped += () => {
Console.WriteLine ("Tapped");
if (accessoryTapped != null) {
accessoryTapped();
}
};
So you'll need to create PostSummaryElement objects in following way:
var myElement = new PostSummaryElement() {
accessoryTapped = someFunction,
}
...
void someFunction()
{
NavigationController.PushViewController (new MyDemoController("Details"), true);
}

Resources