All of my property values require me to click them in order to see them. How can I fix this?
The object I'm trying to view is this Query Object. It seems to do this with most Arcgis objects I'm trying to view.
You can try putting it through JSON stringify which will call all the getters:
console.log(JSON.parse(JSON.stringify(myObj)));
The issue is, calling a getter can have side effects e.g.
class Dog {
get paws() {
console.log('paws!'); //side effect
this.paws++; // side effect
if(this.paws > 4) {
throw Error('oh no'); // side effect
}
return this.paws;
}
}
Every getter can alter the state of the app or break it while you are trying to debug it. That's why DevTools ask you to invoke these getters manually. Even if your getter returns a static value, DevTools have no way of knowing that.
If you really want to invoke all getters and have a quick overview of the values, you can create yourself a helper:
class Dog {
get _debug() {
return {
paws: this.paws,
//...
};
}
}
This will add a new getter that will invoke all other getters for you and give you their values with a single click (instead of n clicks).
You can work-around this, by running a script to auto-invoke the getters. To do this:
Open DevTools in a separate window.
Press CTRL+SHIFT+I
Switch to the console tab (of the devtools inspecting devtools)
Evaluate the below, and close the window
setInterval(() => {
[...document.querySelectorAll(".source-code")]
.map(s => [
...(s.shadowRoot?.querySelectorAll(
".object-value-calculate-value-button"
) || [])
])
.flat()
.forEach(s => s.click());
}, 500);
This will search for the invoke property button every 500ms. and click it for you.
Related
I'm using google_maps_flutter and wish to perform an action when the user performs a gesture on the map, whether it be zoom/tilt/move/rotate. However I'm unable to use the onCameraMoveStarted property in GoogleMap class as it also recognizes non-gesture user action caused as well as programmed animations (which my app utilizes), with no way (as far as I know, please correct me otherwise), to differentiate between them.
Thus I thought of using the flutter widget GestureDetector, wrapping the map inside it so that I would be able to change variables based on the gestures detected by GestureDetector to cause changes indirectly in the map.
No problems initially, it acts as a transparent layer and the map can be moved/tilted/rotated/zoomed normally. However, upon adding a function to execute through onPanStart, onPanUpdate, or onPanEnd all make the map unable to be interacted with through gestures. I suppose it is all being captured by the GestureDetector, but is there no way I can do said extra task asynchronously while passing the gesture along to the child anyway?
Here's the structure, btw:
build(context) {
return Scaffold(
body: GestureDetector(
behavior: HitTestBehavior.deferToChild,
onPanStart: {...}
child:
GoogleMap(...),
),
...
);
}
Thanks in advance, any help much appreciated.
I've found a solution, which might work for you.
class Test extends DragGestureRecognizer {
Function _test;
Test(this._test);
#override
void resolve(GestureDisposition disposition) {
super.resolve(disposition);
this._test();
}
}
...
return GoogleMap(
...
gestureRecognizers: Set()
..add(Factory<DragGestureRecognizer>(() => Test(() {
if (_focusEnabled) {
setState(() {
_focusEnabled = false;
});
}
})),
);
This runs your function on every interaction with the map.
But i did'nt find a way to differentiate between the events.
This may help some, saw this somewhere and forgot about it. Wrap the map in a listener:
Listener(
onPointerDown: (e) {
print("USER IS DRAGGING");
print(e);
},
In the N+1 video #34 (Progress), there was an example of using CreateBindingSet() for the Android version, which is not typical. But the narrator also mentioned briefly that the same can be done on the Windows platform.
As much as I tried, however, I am unable to get a View's property to be bound to its ModelView on the Windows Phone. I always get a NullReferenceException.
The closest I came was the code below, including suggestions from ReSharper. Here's my FirstView.xaml.cs:
using Cirrious.MvvmCross.Binding.BindingContext;
using Whatever.ViewModels;
namespace Whatever {
// inheriting from IMvxBindingContextOwner was suggested by ReSharper also
public partial class FirstView : BaseView, IMvxBindingContextOwner {
public class MyBindableMediaElement
{
private string _theMediaSource = "whatever";
public string TheMediaSource
{
get
{
return _theMediaSource;
}
set
{
_theMediaSource = value;
}
}
}
public FirstView()
{
InitializeComponent();
_mediaElement = new MyBindableMediaElement(this.theMediaElement);
var set = this.CreateBindingSet<FirstView, FirstViewModel>();
// the corresponding view model has a .SongToPlay property with get/set defined
set.Bind(_mediaElement).For(v => v.TheMediaSource).To(vm => vm.SongToPlay);
set.Apply();
}
public IMvxBindingContext BindingContext { get; set; } // this was suggested by ReSharper
}
I get a NullReferenceException in MvxBaseFluentBindingDescription.cs as soon as the view is created. The exact location is below:
protected static string TargetPropertyName(Expression<Func<TTarget, object>> targetPropertyPath)
{
var parser = MvxBindingSingletonCache.Instance.PropertyExpressionParser; // <----- exception here**
var targetPropertyName = parser.Parse(targetPropertyPath).Print();
return targetPropertyName;
}
I have not seen a working example of creating a binding set on a Windows Phone emulator. Has anyone gotten this to work? Thanks.
I can confirm that the narrator said that remark a little too flippantly without actually thinking about how he might do it...
However, with a little effort, you definitely can get the CreateBindingSet to work in Windows if you want to.
Before you start, do consider some alternatives - in particular, I suspect most people will use either Windows DependencyProperty binding or some hand-crafted code-behind with a PropertyChanged event subscription.
If you do want to add CreateBindingSet code to a Windows project then:
Add the Binding and BindingEx assemblies to your Ui project - the easiest way to do this is using nuget to add the BindingEx package.
In your Setup class, override InitializeLastChance and use this opportunity to create a MvxWindowsBindingBuilder instance and to call DoRegistration on that builder. Both these first two steps are covered in the n=35 Tibet binding video - and it's this second step that will initialise the binding framework and help you get past your current 'NullReferenceException' (for the code, see BindMe.Store/Setup.cs)
In your view, you'll need to implement the IMvxBindingContextOwner interface and you'll need to ensure the binding context gets created. You should be able to do this as simply as BindingContext = new MvxBindingContext();
In your view, you'll need to make sure the binding context is given the same DataContext (view model) as the windows DataContext. For a Phone Page, the easiest way to do this is probably just to add BindingContext.DataContext = this.ViewModel; to the end of your phone page's OnNavigatedTo method. Both steps 3 and 4 could go in your BaseView if you intend to use Mvx Binding in other classes too.
With this done, you should be able to use the CreateBindingSet code - although do make sure that all binding is done after the new MvxBindingContext() has been created.
I've not got a windows machine with me right now so I'm afraid this answer code comes untested - please do post again if it does or doesn't work.
I can confirm it works almost perfectly; the only problem is, there are no defaults register, so one has to do the full binding like:
set.Bind(PageText).For(c => c.Text).To(vm => vm.Contents.PageText).OneTime();
to fix this, instead of registering MvxWindowsBindingBuilder, I am registering the following class. Note: I have just created this class, and needs testing.
public class UpdatedMvxWindowsBindingBuilder : MvxWindowsBindingBuilder
{
protected override void FillDefaultBindingNames(IMvxBindingNameRegistry registry)
{
base.FillDefaultBindingNames(registry);
registry.AddOrOverwrite(typeof(Button), "Command");
registry.AddOrOverwrite(typeof(HyperlinkButton), "Command");
//registry.AddOrOverwrite(typeof(UIBarButtonItem), "Clicked");
//registry.AddOrOverwrite(typeof(UISearchBar), "Text");
//registry.AddOrOverwrite(typeof(UITextField), "Text");
registry.AddOrOverwrite(typeof(TextBlock), "Text");
//registry.AddOrOverwrite(typeof(UILabel), "Text");
//registry.AddOrOverwrite(typeof(MvxCollectionViewSource), "ItemsSource");
//registry.AddOrOverwrite(typeof(MvxTableViewSource), "ItemsSource");
//registry.AddOrOverwrite(typeof(MvxImageView), "ImageUrl");
//registry.AddOrOverwrite(typeof(UIImageView), "Image");
//registry.AddOrOverwrite(typeof(UIDatePicker), "Date");
//registry.AddOrOverwrite(typeof(UISlider), "Value");
//registry.AddOrOverwrite(typeof(UISwitch), "On");
//registry.AddOrOverwrite(typeof(UIProgressView), "Progress");
//registry.AddOrOverwrite(typeof(IMvxImageHelper<UIImage>), "ImageUrl");
//registry.AddOrOverwrite(typeof(MvxImageViewLoader), "ImageUrl");
//if (_fillBindingNamesAction != null)
// _fillBindingNamesAction(registry);
}
}
This is a skeleton from Touch binding, and so far I have only updated three controls to test out (Button, HyperButton and TextBlock)
In our App we have a log-in ViewController A. On user log-in, a request navigate is automatically called to navigate to the next ViewController B. However when this is done we want to remove the log-in ViewController A from the stack so the user cannot "go back" to the log-in view but goes back the previous ViewController before the log-in instead.
We thought about removing the ViewController A from the stack when ViewController B is loaded, but is there a better way?
In the Android version of the App we've set history=no (if I recall correctly) and then it works.
Is there an similar way to achieve this in MonoTouch and MvvmCross?
I ended up with removing the unwanted viewcontroller from the navigation controller. In ViewDidDisappear() of my login ViewController I did the following:
public override void ViewDidDisappear (bool animated)
{
if (this.NavigationController != null) {
var controllers = this.NavigationController.ViewControllers;
var newcontrollers = new UIViewController[controllers.Length - 1];
int index = 0;
foreach (var item in controllers) {
if (item != this) {
newcontrollers [index] = item;
index++;
}
}
this.NavigationController.ViewControllers = newcontrollers;
}
base.ViewDidDisappear(animated);
}
This way I way remove the unwanted ViewController when it is removed from the view. I am not fully convinced if it is the right way, but it is working rather good.
This is quite a common scenario... so much so that we've included two mechanisms inside MvvmCross to allow this....
a ClearTop parameter available in all ViewModel navigations.
a RequestRemoveBackStep() call in all ViewModels - although this is currently NOT IMPLEMENTED IN iOS - sorry.
If this isn't enough, then a third technique might be to use a custom presenter to help with your display logic.
To use : 1. a ClearTop parameter available in all ViewModel navigations.
To use this, simply include the ClearTop flag when navigating.
This is a boolean flag - so to use it just change:
this.RequestNavigate<ChildViewModel>(new {arg1 = val1});
to
this.RequestNavigate<ChildViewModel>(new {arg1 = val1}, true);
For a standard simple navigation controller presenter, this will end up calling ClearBackStack before your new view is shown:
public override void ClearBackStack()
{
if (_masterNavigationController == null)
return;
_masterNavigationController.PopToRootViewController (true);
_masterNavigationController = null;
}
from https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.Touch/Views/Presenters/MvxTouchViewPresenter.cs
If you are not using a standard navigation controller - e.g. if you had a tabbed, modal, popup or split view display then you will need to implement your own presentation logic to handle this.
You can't: 2. RequestRemoveBackStep().
Sadly it proved a bit awkward to implement this at a generic level for iOS - so currently that method is:
public bool RequestRemoveBackStep()
{
#warning What to do with ios back stack?
// not supported on iOS really
return false;
}
from https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.Touch/Views/MvxTouchViewDispatcher.cs
Sorry! I've raised a bug against this - https://github.com/slodge/MvvmCross/issues/80
3. You can always... Custom ideas
If you need to implement something custom for your iOS app, the best way is to do this through some sort of custom Presenter logic.
There are many ways you could do this.
One example is:
for any View or ViewModel which needs to clear the previous view, you could decorate the View or ViewModel with a [Special] attribute
in Show in your custom Presenter in your app, you could watch for that attribute and do the special behaviour at that time
public override void Show(MvxShowViewModelRequest request)
{
if (request.ViewModelType.GetCustomAttributes(typeof(SpecialAttribute), true).Any())
{
// do custom behaviour here - e.g. pop current view controller
}
base.Show(request);
}
Obviously other mechanisms might be available - it's just C# and UIKit code at this stage
I don't know about mvvm but you can simply Pop the viewcontroller (AC A) without animation and then push the new viewcontoller (AC B) with animation
From within AC A:
NavigationController.PopViewControllerAnimated(false);
NavigationController.PushViewController(new ACb(), true);
I am trying to add a ScrollBar. The ScrollBar will iterate through the documents displayed. However, I am having trouble receiving an event when the scroll bar changes. I'm not sure what I need to listen to, and I'm not sure what event I should be responding to. I tried the following and I get some events, but I don't think these are the ideal events to handle.
listenTo(scrollBar)
listenTo(scrollBar.keys)
listenTo(scrollBar.mouse.moves)
listenTo(scrollBar.mouse.wheel)
listenTo(scrollBar.mouse.clicks)
For example, I only get MouseClicked, MousePressed, and MouseReleased when I click inside the scrollbar--not when I click on the arrows to actually change the value.
I found this discussion about scroll bars not receiving events properly, but it's two years old. As far as I can tell, the author did not follow up an file a ticket. Maybe he found a workaround.
Any ideas?
Good question. Clicking on arrows isn't handled by ScrollBar, it's handled by ScrollBarUI. I believe that default implementation(or at least base class for majority of ScrollBarUI implementations) is BasicScrollBarUI.
If you'll take a look into source of javax.swing.plaf.basic.BasicScrollBarUI it has incrButton and decrButton buttons and they are components you want listen to.
P.S. I had similar need for having custom (key) listener for my Slider and having custom ui which exposes needed components/model(as you could see almost all components are protected so you easy could access them in subclasses and expose via public getters) worked great for me. I did that in plain java though, maybe in scala you can listen to buttons just by specyfying property name.
One more piece of Scala Swing being broken. The Adjustable trait seems to be completely hollow, nothing is wired.
The following works:
class ScrollBarAlive extends swing.ScrollBar {
me =>
peer.addAdjustmentListener(new java.awt.event.AdjustmentListener {
def adjustmentValueChanged(e: java.awt.event.AdjustmentEvent) {
publish(new swing.event.ValueChanged(me))
}
})
}
Test:
import swing._
object ScrollBarTest extends SimpleSwingApplication {
lazy val top = new Frame {
val label = new Label { text = "0" }
val scroll = new ScrollBarAlive {
orientation = Orientation.Horizontal
listenTo(this)
reactions += {
case event.ValueChanged(_) =>
label.text = value.toString + (if (valueIsAjusting) " A" else "")
}
}
contents = new BorderPanel {
add(label, BorderPanel.Position.North)
add(scroll, BorderPanel.Position.South)
}
pack().centerOnScreen()
open()
}
}
A proper implementation would also introduce a subtype of AdjustingEvent.
I was trying to filter a combo box dataprovider based on the values in the text boxes . When the contents of the dataprovider changes Combo box automatically calls change event method . Please find the sample code below.
Filter Utility Function:
private function filterLocations(event:FocusEvent):void {
locationsList1.filterFunction = filterUtility;
locationsList1.refresh();
}
public function filterUtility(item:Object):Boolean {
// pass back whether the location square foot is with in the range specified
if((item.SQUARE_FOOTAGE >= rangeText1.text) && (item.SQUARE_FOOTAGE rangeText2.text))
return item.SQUARE_FOOTAGE;
}
// THIS WOULD BE CALLED WHEN COMBO BOX SELECTION IS DONE
private function selectLocationsReports(event:ListEvent):void {
selectedItem =(event.currentTarget as ComboBox).selectedItem.LOCATION_ID;
}
When the DataProvider gets refreshed its automatically calls change method and was throwing Null Pointer function because its prematurely calling the above selectLocationsReports method and its throwing error.
Can somebody let me know how to stop the CHANGE event from propogation when the dataprovider is refreshed.
You can't stop a CHANGE event, just don't add an event listener unless you are prepared to get the event. I don't see where your event listener for Event.CHANGE is in the code above.
Just be sure that you don't addEventListener(Event.CHANGE, selectLocationsReports) until your ComboBox is ready for it.
The other thing to do (on top of Kekoa's response) is put an if statement in the event handler, and check to make sure the data is there before you begin working with it.
A handy syntax I use frequently for this is
if(dataprovidername) {
}