问:
Passing js variable to php using ajax does not work
I want to get variable rating_idex in my php file so if is user click button #add-review it should pass in ajax variable and it will get array in php file and send review to the database, but it is not working and I don't see solution

```<code>$('#add-review').click(function(){
    var user_name = $('#reviewer-name').val();
    var user_review = $('#review').val();
    console.log(user_name);
    console.log(rating_index);
    console.log(user_review);
    if(user_name == '' || user_review == '')
    {
        alert("Please Fill Both Field");
        return false;
    }
    else
    {
        $.ajax({
            url:"rating-data.php",
            method:"GET",
            data:{
                rating_index: rating_index,
                user_name: user_name,
                user_review: user_review
            },
            success:function(data)
            {
                $('#review_modal').modal('hide');
                load_rating_data();
                console.log(data);
            }
        })
    }
});
</code>```

This is my php code when I can get the variable and send them to the database:

```<code><?php
include 'connection.php';
echo ($rating_index);
if(isset($_GET["rating_index"]))
{
    $data = array(
        ':user_name'        =>  $_GET["user_name"],
        ':user_rating'      =>  $_GET["rating_index"],
        ':user_review'      =>  $_GET["user_review"],
        ':datetime'         =>  time()
    );
    $query = "
    INSERT INTO review_table
    (user_name, user_rating, user_review, datetime)
    VALUES (:user_name, :user_rating, :user_review, :datetime)
    ";

    $query_run = mysqli_query($conn, $query);
    if($query_run){
        echo "Your Review & Rating Successfully Submitted";
    } else{
        echo '<script type="text/javascript"> alert("Something went wrong") </script>';
        echo mysqli_error($conn);
    }
}
?>
</code>```

When I am trying to echo ($rating_index) it give me feedback that variable does not exist so it is something with ajax but can't find solution, thanks in advance for any solutions

答: Instead of echo ($rating_index); try echo ($_GET["rating_index"]); reason being you didn't actually declared $rating_index

Body:
I want to get variable rating_idex in my php file so if is user click button #add-review it should pass in ajax variable and it will get array in php file and send review to the database, but it is not working and I don't see solution

$('#add-review').click(function(){
    var user_name = $('#reviewer-name').val();
    var user_review = $('#review').val();
    console.log(user_name);
    console.log(rating_index);
    console.log(user_review);
    if(user_name == '' || user_review == '')
    {
        alert("Please Fill Both Field");
        return false;
    }
    else
    {
        $.ajax({
            url:"rating-data.php",
            method:"GET",
            data:{
                rating_index: rating_index,
                user_name: user_name,
                user_review: user_review
            },
            success:function(data)
            {
                $('#review_modal').modal('hide');
                load_rating_data();
                console.log(data);
            }
        })
    }
});

This is my php code when I can get the variable and send them to the database:

<?php
include 'connection.php';
echo ($rating_index);
if(isset($_GET["rating_index"]))
{
    $data = array(
        ':user_name'        =>  $_GET["user_name"],
        ':user_rating'      =>  $_GET["rating_index"],
        ':user_review'      =>  $_GET["user_review"],
        ':datetime'         =>  time()
    );
    $query = "
    INSERT INTO review_table
    (user_name, user_rating, user_review, datetime)
    VALUES (:user_name, :user_rating, :user_review, :datetime)
    ";

    $query_run = mysqli_query($conn, $query);
    if($query_run){
        echo "Your Review & Rating Successfully Submitted";
    } else{
        echo '';
        echo mysqli_error($conn);
    }
}
?>

When I am trying to echo ($rating_index) it give me feedback that variable does not exist so it is something with ajax but can't find solution, thanks in advance for any solutions


来源: stackexchange

问:
Typescript - Give type info to AND extract type info from same object
Say I'm working with sound designers and want them to get good information while editing configuration files.
I think @eventsA below works fine for that purpose.
But then I would also like to get good type information in the rest of the application from those configs for the devs, and then I think @eventsB works well.
How can I get the best of both? That is errors when editing config files AND be able to extract specific types from the configs for use within the rest of the application.

```<code>interface IEvent {
    id: string
    actions: Array<{
        func: "setMasterVolume" | "playSound",
        args: Array<string | number | boolean>
    }>
}

// With type that is helpfull for sound designer
const eventsA: Array<IEvent> = [
    {
        foo: "bar", // this line will give error to sound designer because not in interface
        id: "start",
        actions: [
            {
                func: "setMasterVolume",
                args: [ 1 ]
            }
        ]
    },
    {
        id: "stop",
        actions: [
            {
                func: "setMasterVolume",
                args: [ 0 ]
            }
        ]
    }
]

// This only gives unspecific 'string' type
type AudioEventsA = typeof eventsA[number]['id']

// With type that is helpfull for developer
const eventsB = [
    {
        foo: "bar", // now no error on this line unfortunately
        id: "start",
        actions: [
            {
                func: "setMasterVolume",
                args: [ 1 ]
            }
        ]
    },
    {
        id: "stop",
        actions: [
            {
                func: "setMasterVolume",
                args: [ 0 ]
            }
        ]
    }
] as const

// Now I can extract type of: 'start' | 'stop' rather than just string.
type AudioEventsB = typeof eventsB[number]['id']

</code>```

So how to get both error at: foo: "bar" and get AudioEvents = 'start' | 'stop'

答:
I think you could make your interface accept the expected types as generics. And since you allow your developers to create arrays with const assertions you have to tpye your arrays as readonly. To specify what types of arrays your developers are allowed to create you can create the type Iarr and they pass it the types they decide they are gonna need for their arrays.

```<code>export type Func = "setMasterVolume" | "playSound";

interface IEvent<T extends string, F extends Func, A extends string | number | boolean> {
    id: T
    actions: readonly{
        func: F,
        args: readonly A[]
    }[]
}

export type Iarr = readonly IEvent<'start'|'stop', "setMasterVolume", number>[];

// With type that is helpfull for sound designer
const eventsA: Iarr = [
    {
        foo: "bar", // this line will give error to sound designer because not in interface
        id: "start",
        actions: [
            {
                func: "setMasterVolume",
                args: [ 1 ]
            }
        ]
    },
    {
        id: "stop",
        actions: [
            {
                func: "setMasterVolume",
                args: [ 0 ]
            }
        ]
    }
]

// This only gives unspecific 'string' type
type AudioEventsA = typeof eventsA[number]['id']

// With type that is helpfull for developer
const eventsB: Iarr = [
    {
        foo: "bar", // now no error on this line unfortunately
        id: "start",
        actions: [
            {
                func: "setMasterVolume",
                args: [ 1 ]
            }
        ]
    },
    {
        id: "stop",
        actions: [
            {
                func: "setMasterVolume",
                args: [ 0 ]
            }
        ]
    }
] as const

// Now I can extract type of: 'start' | 'stop' rather than just string.
type AudioEventsB = typeof eventsB[number]['id']
</code>```

ContentLicense: CC BY-SA 4.0

Body:
Say I'm working with sound designers and want them to get good information while editing configuration files.
I think @eventsA below works fine for that purpose.
But then I would also like to get good type information in the rest of the application from those configs for the devs, and then I think @eventsB works well.
How can I get the best of both? That is errors when editing config files AND be able to extract specific types from the configs for use within the rest of the application.

interface IEvent {
    id: string
    actions: Array<{
        func: "setMasterVolume" | "playSound",
        args: Array<string | number | boolean>
    }>
}

// With type that is helpfull for sound designer
const eventsA: Array<IEvent> = [
    {
        foo: "bar", // this line will give error to sound designer because not in interface
        id: "start",
        actions: [
            {
                func: "setMasterVolume",
                args: [ 1 ]
            }
        ]
    },
    {
        id: "stop",
        actions: [
            {
                func: "setMasterVolume",
                args: [ 0 ]
            }
        ]
    }
]

// This only gives unspecific 'string' type
type AudioEventsA = typeof eventsA[number]['id']

// With type that is helpfull for developer
const eventsB = [
    {
        foo: "bar", // now no error on this line unfortunately
        id: "start",
        actions: [
            {
                func: "setMasterVolume",
                args: [ 1 ]
            }
        ]
    },
    {
        id: "stop",
        actions: [
            {
                func: "setMasterVolume",
                args: [ 0 ]
            }
        ]
    }
] as const

// Now I can extract type of: 'start' | 'stop' rather than just string.
type AudioEventsB = typeof eventsB[number]['id']

So how to get both error at: foo: "bar" and get AudioEvents = 'start' | 'stop'

Body:
I think you could make your interface accept the expected types as generics. And since you allow your developers to create arrays with const assertions you have to tpye your arrays as readonly. To specify what types of arrays your developers are allowed to create you can create the type Iarr and they pass it the types they decide they are gonna need for their arrays.

export type Func = "setMasterVolume" | "playSound";

interface IEvent<T extends string, F extends Func, A extends string | number | boolean> {
    id: T
    actions: readonly{
        func: F,
        args: readonly A[]
    }[]
}

export type Iarr = readonly IEvent<'start'|'stop', "setMasterVolume", number>[];

// With type that is helpfull for sound designer
const eventsA: Iarr = [
    {
        foo: "bar", // this line will give error to sound designer because not in interface
        id: "start",
        actions: [
            {
                func: "setMasterVolume",
                args: [ 1 ]
            }
        ]
    },
    {
        id: "stop",
        actions: [
            {
                func: "setMasterVolume",
                args: [ 0 ]
            }
        ]
    }
]

// This only gives unspecific 'string' type
type AudioEventsA = typeof eventsA[number]['id']

// With type that is helpfull for developer
const eventsB: Iarr = [
    {
        foo: "bar", // now no error on this line unfortunately
        id: "start",
        actions: [
            {
                func: "setMasterVolume",
                args: [ 1 ]
            }
        ]
    },
    {
        id: "stop",
        actions: [
            {
                func: "setMasterVolume",
                args: [ 0 ]
            }
        ]
    }
] as const

// Now I can extract type of: 'start' | 'stop' rather than just string.
type AudioEventsB = typeof eventsB[number]['id']


问:
error Couldn't find "PLATFORM_NAME" variable in xcodebuild output
I'm trying to run my application on an iPhone simulator. from the console, I can see the build was successful. but on the next line, I get this.

error Couldn't find "PLATFORM_NAME" variable in xcodebuild output. Please report this issue and run your project with Xcode instead. react-native.

答:
Context: react-native upgrade fails and cleaning the build folder doesn't work.

What works:

Trash out the node_modules folder.

Make yarn install to re-create dependencies.

It doesn't have any impact on "Podfile", but if you (future users) did, remove Podfile.lock, go to the ios folder and run pod install again. It must solve.


问:
How can a Qt ONVIF application be created?
I want to create an application to control camera parameters (users/ptz/get video). The camera is using the ONVIF protocol.

I am using Qt framework 5.13.

I found gsoap tool and .wsdl files from onfiv.com. Then i use guide from https://www.genivia.com/examples/onvif/index.html to create .h/.cpp files from devicemanagement.wsdl.
I have generated one proxy class from devicemanagement.wsdl, and the program on Qt with generated files is working, but I need user authorization and ptz control...

How can I use gsoap, onvif specifications files(.wsdl) to generate class, which user authorization and ptz control for Qt?

Maybe someone makes the same application on Qt and can help me.

答:
Run wsdl2h on the ptz.wsdl:

```<code>wsdl2h -O4 -P -x -o onvif.h http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl
</code>```

This assumes you have the typemap.dat file in the current directory with the ONVIF namespace bindings, see the ONVIF example to get that file.

Option -O4 aggressively "slices" the WSDL to reduce code size only to the necessary components, see article Schema Slicing Methods to Reduce Development Costs of WSDL-Based Web Services.

To generate C++ proxy classes:

```<code>soapcpp2 -C -j -2 -I gsoap/import onvif.h
</code>```

The -C option specifies client-only, -j specifies proxy classes, -2 specifies SOAP 1.2 enforcement, -I is to import the necessary files.

If you need WS-Security authentication, then add the line:

```<code>#import "wsse.h"
</code>```

to the onvif.h file if not already there, then rerun soapcpp2.

Compile:

```<code>c++ -O2 -I. -Igsoap/custom -o app soapPTZBindingProxy.cpp soapC.cpp dom.cpp stdsoap2.cpp wsseapi.c
</code>```

Some source code files are generated, others are part of the gSOAP libraries.

The code generation tools have lots of options, so it depends a bit on what you want to accomplish.

If you want to use QT strings and types, then this can be done too with a modification of the typemap.dat file and by using the custom serializers located in gsoap/custom. For example, custom/qstring.h tells you to:

```<code>        To automate the wsdl2h-mapping of xsd:string to
        QString, add this line to the typemap.dat file:

        xsd__string = #import "custom/qstring.h" | xsd__string
</code>```

Then rerun wsdl2h to get the QT string binding. Compile custom/qtstring.cpp with your project.

Body:
Run wsdl2h on the ptz.wsdl:

wsdl2h -O4 -P -x -o onvif.h http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl

This assumes you have the typemap.dat file in the current directory with the ONVIF namespace bindings, see the ONVIF example to get that file.

Option -O4 aggressively "slices" the WSDL to reduce code size only to the necessary components, see article Schema Slicing Methods to Reduce Development Costs of WSDL-Based Web Services.

To generate C++ proxy classes:

soapcpp2 -C -j -2 -I gsoap/import onvif.h

The -C option specifies client-only, -j specifies proxy classes, -2 specifies SOAP 1.2 enforcement, -I is to import the necessary files.

If you need WS-Security authentication, then add the line:

#import "wsse.h"

to the onvif.h file if not already there, then rerun soapcpp2.

Compile:

c++ -O2 -I. -Igsoap/custom -o app soapPTZBindingProxy.cpp soapC.cpp dom.cpp stdsoap2.cpp wsseapi.c

Some source code files are generated, others are part of the gSOAP libraries.

The code generation tools have lots of options, so it depends a bit on what you want to accomplish.

If you want to use QT strings and types, then this can be done too with a modification of the typemap.dat file and by using the custom serializers located in gsoap/custom. For example, custom/qstring.h tells you to:

        To automate the wsdl2h-mapping of xsd:string to
        QString, add this line to the typemap.dat file:

        xsd__string = #import "custom/qstring.h" | xsd__string

Then rerun wsdl2h to get the QT string binding. Compile custom/qtstring.cpp with your project.


问:
How do I close my MVVM popup using the MVVM format without a framework
First let me start by stating I did go through about 40 similar questions here on stack overflow (and lots of google results), a majority of answers use some sort of framework. The few answers that don't use a framework link to their blog post where they wrote several hundreds lines creating a generic method, or some overly complicated solution that doesn't really apply to my scenario. Some of the answers link to an already answered post that is 10 or more years old, and the answer is using a method that is outdated by newer releases, and doesn't work.

I am trying to create a simple error popup. The popup has a label and an ok button.

Pressing the OK button on the popup should close the popup.

I have everything working but the close. I just need a simple solution that follows MVVM so that I can unit test the code. I don't need a framework that will fit hundreds of different scenarios, I just need the popup to close.

I have tried almost every suggested answer here on stack overflow, and ones I found googling. But I was unable to get any working. After 2 and a half days I've given up and am looking for an answer. I'm sure I was close at some point but...

I created a stripped down version of my project that is below. Can anyone show me what I need to do in order to close the popup?

MainWindow.xaml

```<code><Window.DataContext>
    <local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
    <Button HorizontalAlignment="Center" VerticalAlignment="Center" Content="Open Dialog" Command="{Binding ShowErrorPopup}"/>
</Grid>
</code>```

MainWindowViewModel.cs

```<code>class MainWindowViewModel
{
    public ICommand ShowErrorPopup
    {
        get;
        set;
    }

    public MainWindowViewModel()
    {
        ShowErrorPopup = new RelayCommand(new Action<object>(ExecuteShowErrorPopup));
    }

    public void ExecuteShowErrorPopup(object obj)
    {
        ErrorPopupService errorPopupNav = new ErrorPopupService();
        errorPopupNav.CreateErrorPopup("Test Message");
    }
}
</code>```

ErrorPopup.xaml

```<code> <Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Label Grid.Row="0" Content="{Binding ErrorMessage}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Red" FontSize="14" FontWeight="Bold"/>
    <Button Grid.Row="1" Content="OK" Width="100" Margin="4" HorizontalAlignment="Right" Command="{Binding CloseWindowCommand, Mode=OneWay}" CommandParameter="{Binding ElementName=ErrorPopupWindow}"/>
</Grid>
</code>```

ErrorPopupViewModel.cs

```<code>class ErrorPopupViewModel
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private String m_errorMessage;

    public String ErrorMessage
    {
        get
        {
            return m_errorMessage;
        }
        private set
        {
            m_errorMessage = value;
            OnPropertyChanged(ErrorMessage);
        }
    }

    public ErrorPopupViewModel(String ErrorMessageToDisplay)
    {
        ErrorMessage = ErrorMessageToDisplay;
    }
}
</code>```

ErrorPopupService.cs

```<code>interface ErrorPopupServiceInterface
{
    void CreateErrorPopup(String ErrorMessage);
}

class ErrorPopupService : ErrorPopupServiceInterface
{
    private ErrorPopup m_errorPopup;

    public void CreateErrorPopup(String ErrorMessage)
    {
        m_errorPopup = new ErrorPopup
        {
            DataContext = new ErrorPopupViewModel(ErrorMessage)
        };
        m_errorPopup.Show();
    }
}
</code>```

RelayCommand.cs

```<code>class RelayCommand : ICommand
{
    private Action<object> _action;

    public RelayCommand(Action<object> action)
    {
        _action = action;
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        _action(parameter);
    }
}
</code>```

答:
After working on this more I was able to find a solution. I am passing in the Dialogs close command as an action to the dialogs view model. I have posted the bare minimum code that I used below.

If there is a problem with this solution, breaking the MVVM standards, or there is a better, simpler solution please post it.

ErrorPopup.xaml, and ErrorPopupViewModel.cs were in a folder named Dialogs.
ObservableObjects.cs, and RelayCommand.cs were in a folder named Helpers

MainWindow.xaml

```<code><Window x:Class="Dialog.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Dialog"
    mc:Ignorable="d"
    Title="MainWindow" Height="150" Width="400">
<Window.DataContext>
    <local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
    <Button  Command="{Binding NewModelessDialogCommand}" HorizontalAlignment="Center" VerticalAlignment="Center" Content="Open Dialog" />
</Grid>
</Window>
</code>```

MainWindowViewModel.cs

```<code>using System;
using System.Windows.Input;
using Dialog.Helpers;
using Dialog.Dialogs;

namespace Dialog
{
    class MainWindowViewModel
    {
        private ErrorPopup m_errorPopup;
        private ICommand m_newModelessDialogCommand;

        public ICommand NewModelessDialogCommand
        {
            get
            {
                return m_newModelessDialogCommand;
            }
            private set
            {
                m_newModelessDialogCommand = value;
            }
        }

        public MainWindowViewModel()
        {
            NewModelessDialogCommand = new RelayCommand(new Action<object>(OpenDialog));
        }

        public void OpenDialog(object obj)
        {
            m_errorPopup = new ErrorPopup
            {
                DataContext = new ErrorPopupViewModel(() => CloseDialog())
                {
                    Message = "Error Message!"
                }
            };
            m_errorPopup.Show();
        }

        public void CloseDialog()
        {
            if (m_errorPopup != null)
            {
                m_errorPopup.Close();
            }
        }
    }
}
</code>```

ErrorPopup.xaml

```<code><Window x:Class="Dialog.Dialogs.ErrorPopup"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Dialog.Dialogs"
    mc:Ignorable="d"
    WindowStartupLocation="CenterOwner" WindowStyle="None"
    Title="{Binding Caption}" Height="170" Width="300" ResizeMode="NoResize" >
<Grid>
    <TextBlock Text="{Binding Message}" HorizontalAlignment="Center" Margin="0,50,0,0" TextWrapping="Wrap" VerticalAlignment="Top"/>
    <Button Content="Ok" Command="{Binding OkCommand}" HorizontalAlignment="Center" Margin="0,100,0,0" VerticalAlignment="Top" Width="75" IsDefault="True" />
</Grid>
</code>```

ErrorPopup.cs

```<code>using System;
using System.Windows.Input;
using Dialog.Helpers;

namespace Dialog.Dialogs
{
    public class ErrorPopupViewModel : ObservableObject
    {
        private string m_message;
        private ICommand m_OkCommand;
        private Action m_closeCommand;

        public string Message
        {
            get
            {
                return m_message;
            }
            set
            {
                m_message= value;
                RaisePropertyChanged("Message");
            }
        }

        public ICommand OkCommand
        {
            get
            {
                return m_OkCommand;
            }
            private set
            {
                m_OkCommand = value;
            }
        }

        public ErrorPopupViewModel(Action closeCommand)
        {
            OkCommand = new RelayCommand(new Action<object>(Ok));

            m_closeCommand = closeCommand;
        }

        public void Ok(object obj)
        {
            m_closeCommand();
        }
    }
}
</code>```

ObservableObject.cs

```<code>using System;
using System.ComponentModel;
using System.Linq.Expressions;

namespace Dialog.Helpers
{
    public class ObservableObject : INotifyPropertyChanged
    {
        protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression)

        {
            var memberExpr = propertyExpression.Body as MemberExpression;

            if (memberExpr == null)
            {
                throw new ArgumentException("propertyExpression should represent access to a member");
            }
            string memberName = memberExpr.Member.Name;
            RaisePropertyChanged(memberName);
        }
    }
}
</code>```

RelayCommand.cs

```<code>using System;
using System.Windows.Input;

namespace Dialog.Helpers
{
    public class RelayCommand : ICommand
    {
        public event EventHandler CanExecuteChanged;
        private Action<object> m_action;

        public RelayCommand(Action<object> action)
        {
           m_action= action;
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            m_action(parameter);
        }
    }
}
</code>```

Body:
First let me start by stating I did go through about 40 similar questions here on stack overflow (and lots of google results), a majority of answers use some sort of framework. The few answers that don't use a framework link to their blog post where they wrote several hundreds lines creating a generic method, or some overly complicated solution that doesn't really apply to my scenario. Some of the answers link to an already answered post that is 10 or more years old, and the answer is using a method that is outdated by newer releases, and doesn't work.

I am trying to create a simple error popup. The popup has a label and an ok button.

Pressing the OK button on the popup should close the popup.

I have everything working but the close. I just need a simple solution that follows MVVM so that I can unit test the code. I don't need a framework that will fit hundreds of different scenarios, I just need the popup to close.

I have tried almost every suggested answer here on stack overflow, and ones I found googling. But I was unable to get any working. After 2 and a half days I've given up and am looking for an answer. I'm sure I was close at some point but...

I created a stripped down version of my project that is below. Can anyone show me what I need to do in order to close the popup?

MainWindow.xaml

<Window.DataContext>
    <local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
    <Button HorizontalAlignment="Center" VerticalAlignment="Center" Content="Open Dialog" Command="{Binding ShowErrorPopup}"/>
</Grid>

MainWindowViewModel.cs

class MainWindowViewModel
{
    public ICommand ShowErrorPopup
    {
        get;
        set;
    }

    public MainWindowViewModel()
    {
        ShowErrorPopup = new RelayCommand(new Action<object>(ExecuteShowErrorPopup));
    }

    public void ExecuteShowErrorPopup(object obj)
    {
        ErrorPopupService errorPopupNav = new ErrorPopupService();
        errorPopupNav.CreateErrorPopup("Test Message");
    }
}

ErrorPopup.xaml

 <Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <Button Grid.Row="1" Content="OK" Width="100" Margin="4" HorizontalAlignment="Right" Command="{Binding CloseWindowCommand, Mode=OneWay}" CommandParameter="{Binding ElementName=ErrorPopupWindow}"/>
</Grid>

ErrorPopupViewModel.cs

class ErrorPopupViewModel
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private String m_errorMessage;

    public String ErrorMessage
    {
        get
        {
            return m_errorMessage;
        }
        private set
        {
            m_errorMessage = value;
            OnPropertyChanged(ErrorMessage);
        }
    }

    public ErrorPopupViewModel(String ErrorMessageToDisplay)
    {
        ErrorMessage = ErrorMessageToDisplay;
    }
}

ErrorPopupService.cs

interface ErrorPopupServiceInterface
{
    void CreateErrorPopup(String ErrorMessage);
}

class ErrorPopupService : ErrorPopupServiceInterface
{
    private ErrorPopup m_errorPopup;

    public void CreateErrorPopup(String ErrorMessage)
    {
        m_errorPopup = new ErrorPopup
        {
            DataContext = new ErrorPopupViewModel(ErrorMessage)
        };
        m_errorPopup.Show();
    }
}

RelayCommand.cs

class RelayCommand : ICommand
{
    private Action<object> _action;

    public RelayCommand(Action<object> action)
    {
        _action = action;
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        _action(parameter);
    }
}

Body:
After working on this more I was able to find a solution. I am passing in the Dialogs close command as an action to the dialogs view model. I have posted the bare minimum code that I used below.

If there is a problem with this solution, breaking the MVVM standards, or there is a better, simpler solution please post it.

ErrorPopup.xaml, and ErrorPopupViewModel.cs were in a folder named Dialogs.
ObservableObjects.cs, and RelayCommand.cs were in a folder named Helpers

MainWindow.xaml

<Window x:Class="Dialog.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Dialog"
    mc:Ignorable="d"
    Title="MainWindow" Height="150" Width="400">
<Window.DataContext>
    <local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
    <Button  Command="{Binding NewModelessDialogCommand}" HorizontalAlignment="Center" VerticalAlignment="Center" Content="Open Dialog" />
</Grid>
</Window>

MainWindowViewModel.cs

using System;
using System.Windows.Input;
using Dialog.Helpers;
using Dialog.Dialogs;

namespace Dialog
{
    class MainWindowViewModel
    {
        private ErrorPopup m_errorPopup;
        private ICommand m_newModelessDialogCommand;

        public ICommand NewModelessDialogCommand
        {
            get
            {
                return m_newModelessDialogCommand;
            }
            private set
            {
                m_newModelessDialogCommand = value;
            }
        }

        public MainWindowViewModel()
        {
            NewModelessDialogCommand = new RelayCommand(new Action<object>(OpenDialog));
        }

        public void OpenDialog(object obj)
        {
            m_errorPopup = new ErrorPopup
            {
                DataContext = new ErrorPopupViewModel(() => CloseDialog())
                {
                    Message = "Error Message!"
                }
            };
            m_errorPopup.Show();
        }

        public void CloseDialog()
        {
            if (m_errorPopup != null)
            {
                m_errorPopup.Close();
            }
        }
    }
}

ErrorPopup.xaml

<Window x:Class="Dialog.Dialogs.ErrorPopup"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Dialog.Dialogs"
    mc:Ignorable="d"
    WindowStartupLocation="CenterOwner" WindowStyle="None"
    Title="{Binding Caption}" Height="170" Width="300" ResizeMode="NoResize" >
<Grid>
    <TextBlock Text="{Binding Message}" HorizontalAlignment="Center" Margin="0,50,0,0" TextWrapping="Wrap" VerticalAlignment="Top"/>
    <Button Content="Ok" Command="{Binding OkCommand}" HorizontalAlignment="Center" Margin="0,100,0,0" VerticalAlignment="Top" Width="75" IsDefault="True" />
</Grid>

ErrorPopup.cs

using System;
using System.Windows.Input;
using Dialog.Helpers;

namespace Dialog.Dialogs
{
    public class ErrorPopupViewModel : ObservableObject
    {
        private string m_message;
        private ICommand m_OkCommand;
        private Action m_closeCommand;

        public string Message
        {
            get
            {
                return m_message;
            }
            set
            {
                m_message= value;
                RaisePropertyChanged("Message");
            }
        }

        public ICommand OkCommand
        {
            get
            {
                return m_OkCommand;
            }
            private set
            {
                m_OkCommand = value;
            }
        }

        public ErrorPopupViewModel(Action closeCommand)
        {
            OkCommand = new RelayCommand(new Action<object>(Ok));

            m_closeCommand = closeCommand;
        }

        public void Ok(object obj)
        {
            m_closeCommand();
        }
    }
}

ObservableObject.cs

using System;
using System.ComponentModel;
using System.Linq.Expressions;

namespace Dialog.Helpers
{
    public class ObservableObject : INotifyPropertyChanged
    {
        protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression)

        {
            var memberExpr = propertyExpression.Body as MemberExpression;

            if (memberExpr == null)
            {
                throw new ArgumentException("propertyExpression should represent access to a member");
            }
            string memberName = memberExpr.Member.Name;
            RaisePropertyChanged(memberName);
        }
    }
}

RelayCommand.cs

using System;
using System.Windows.Input;

namespace Dialog.Helpers
{
    public class RelayCommand : ICommand
    {
        public event EventHandler CanExecuteChanged;
        private Action<object> m_action;

        public RelayCommand(Action<object> action)
        {
           m_action= action;
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            m_action(parameter);
        }
    }
}


问:
Show relationships between classes in different packages in a UML class diagram
Would I draw the Arrow out of one package from one class to another or from one package to the other package that the classes are in?</p>

答:
Simply draw the relations "as usual". You can show the packages enlarged so the classes contained inside will appear as being inside. However, there is no need to show the packages. You could as well create package diagrams with just the classes inside and no relations to emphasize the package character.

In general you are free to show whatever fits best / transports the message you want to be shown.

It's recommended to use an UML modeling tool rather than a drawing tool which does not have semantic for elements but only graphic information.


问:
Google Play Sign-in: java.lang.SecurityException Not signed in when calling API
Since 1/17/22, we have been seeing a substantial (hundreds per day) number of crashes in our Android app with the following stack trace:

```<code>Fatal Exception: java.lang.SecurityException: Not signed in when calling API
       at android.os.Parcel.createExceptionOrNull(Parcel.java:2385)
       at android.os.Parcel.createException(Parcel.java:2369)
       at android.os.Parcel.readException(Parcel.java:2352)
       at android.os.Parcel.readException(Parcel.java:2294)
       at com.google.android.gms.internal.games.zzb.zzb(com.google.android.gms:play-services-games@@21.0.0:22)
       at com.google.android.gms.games.internal.zzaf.zza(com.google.android.gms:play-services-games@@21.0.0:259)
       at com.google.android.gms.games.internal.zzf.onConnectedLocked(com.google.android.gms:play-services-games@@21.0.0:752)
       at com.google.android.gms.common.internal.BaseGmsClient.zzp(com.google.android.gms:play-services-basement@@17.6.0:40)
       at com.google.android.gms.common.internal.BaseGmsClient.zzl(:10)
       at com.google.android.gms.common.internal.zzf.zza(com.google.android.gms:play-services-basement@@17.6.0:6)
       at com.google.android.gms.common.internal.zza.zzd(:6)
       at com.google.android.gms.common.internal.zzc.zze(com.google.android.gms:play-services-basement@@17.6.0:3)
       at com.google.android.gms.common.internal.zzb.handleMessage(com.google.android.gms:play-services-basement@@17.6.0:31)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loop(Looper.java:246)
       at android.os.HandlerThread.run(HandlerThread.java:67)
</code>```

We did not change anything with our app during this time, so I believe this was triggered by some update on Google Play Game Services' end.

I see similar reports from a number of years ago, but the common suggestion such as the one in the accepted answer here seems to be using a different API than we do. Our implementation does not use a GoogleApiClient object, but rather a GoogleSignInClient object:

```<code>signInClient.silentSignIn().addOnCompleteListener(new OnCompleteListener<GoogleSignInAccount>() {
@Override
public void onComplete(@NonNull Task<GoogleSignInAccount> task) {
   ...
}
</code>```

This option does not allow for using the GoogleApiClient.disconnect() method, even via GoogleSignInClient.asGoogleApiClient().

Our GoogleSignInClient setup:

```<code>GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
    .requestScopes(new Scope(Scopes.DRIVE_APPFOLDER))
    .requestServerAuthCode("...")
    .build();
signInClient = GoogleSignIn.getClient(mainApplication, gso);
</code>```

Our sign-in handling:

```<code>mainApplication().runOnActivityResult(new ActivityResultListener() {
    @Override
    public void receivedActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == RC_SIGN_IN) {
            OnSignInAttemptComplete(GoogleSignIn.getSignedInAccountFromIntent(data));
        } else if (requestCode == GameHelper.RC_GAME_SERVICES_ACTIVITY) {
            if (resultCode == GamesActivityResultCodes.RESULT_RECONNECT_REQUIRED) {
                //They logged out
                account = null;
                listener.onSignedOut();
            }
        }
    }
});
mainApplication.startActivityForResult(signInClient.getSignInIntent(), RC_SIGN_IN);
</code>```

答: We have not seen any instances of this crash since February 1st, so it seems safe to assume at this point that it was due to an error on GPGS' end which has since been fixed.</p>

Body:
Since 1/17/22, we have been seeing a substantial (hundreds per day) number of crashes in our Android app with the following stack trace:

Fatal Exception: java.lang.SecurityException: Not signed in when calling API
       at android.os.Parcel.createExceptionOrNull(Parcel.java:2385)
       at android.os.Parcel.createException(Parcel.java:2369)
       at android.os.Parcel.readException(Parcel.java:2352)
       at android.os.Parcel.readException(Parcel.java:2294)
       at com.google.android.gms.internal.games.zzb.zzb(com.google.android.gms:play-services-games@@21.0.0:22)
       at com.google.android.gms.games.internal.zzaf.zza(com.google.android.gms:play-services-games@@21.0.0:259)
       at com.google.android.gms.games.internal.zzf.onConnectedLocked(com.google.android.gms:play-services-games@@21.0.0:752)
       at com.google.android.gms.common.internal.BaseGmsClient.zzp(com.google.android.gms:play-services-basement@@17.6.0:40)
       at com.google.android.gms.common.internal.BaseGmsClient.zzl(:10)
       at com.google.android.gms.common.internal.zzf.zza(com.google.android.gms:play-services-basement@@17.6.0:6)
       at com.google.android.gms.common.internal.zza.zzd(:6)
       at com.google.android.gms.common.internal.zzc.zze(com.google.android.gms:play-services-basement@@17.6.0:3)
       at com.google.android.gms.common.internal.zzb.handleMessage(com.google.android.gms:play-services-basement@@17.6.0:31)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loop(Looper.java:246)
       at android.os.HandlerThread.run(HandlerThread.java:67)

We did not change anything with our app during this time, so I believe this was triggered by some update on Google Play Game Services' end.

I see similar reports from a number of years ago, but the common suggestion such as the one in the accepted answer here seems to be using a different API than we do. Our implementation does not use a GoogleApiClient object, but rather a GoogleSignInClient object:

signInClient.silentSignIn().addOnCompleteListener(new OnCompleteListener<GoogleSignInAccount>() {
@Override
public void onComplete(@NonNull Task<GoogleSignInAccount> task) {
   ...
}

This option does not allow for using the GoogleApiClient.disconnect() method, even via GoogleSignInClient.asGoogleApiClient().

Our GoogleSignInClient setup:

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
    .requestScopes(new Scope(Scopes.DRIVE_APPFOLDER))
    .requestServerAuthCode("...")
    .build();
signInClient = GoogleSignIn.getClient(mainApplication, gso);

Our sign-in handling:

mainApplication().runOnActivityResult(new ActivityResultListener() {
    @Override
    public void receivedActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == RC_SIGN_IN) {
            OnSignInAttemptComplete(GoogleSignIn.getSignedInAccountFromIntent(data));
        } else if (requestCode == GameHelper.RC_GAME_SERVICES_ACTIVITY) {
            if (resultCode == GamesActivityResultCodes.RESULT_RECONNECT_REQUIRED) {
                //They logged out
                account = null;
                listener.onSignedOut();
            }
        }
    }
});
mainApplication.startActivityForResult(signInClient.getSignInIntent(), RC_SIGN_IN);


问:
export a variable inside a function to be used in other modules
I'm quite new to programming. I have spend last 3 days trying to figure this out. So any help really appreciate it.

I have access to clientID inside a for loop. (Please look at the last line in the code below). There is only one ClientID which I'm successfully able to print.

I want this client ID to be exported from this module so that I can use it in other modules.

```<code>import { Configurations } from './models';

type MethodNames = 'init' | 'event';

export const DEFAULT_NAME = '_hw';

interface LoaderObject {
    q: Array<[MethodNames, {}]>;
}

export default (
    win: Window,
    defaultConfig: Configurations,
    scriptElement: Element | null,
    render: (element: HTMLElement, config: Configurations) => void
) => {

    const instanceName =
        scriptElement?.attributes.getNamedItem('id')?.value ?? DEFAULT_NAME;
    const loaderObject: LoaderObject = win[instanceName];
    if (!loaderObject || !loaderObject.q) {
        throw new Error(
            `Widget didn't find LoaderObject`);
    }

    if (win[`loaded-${instanceName}`]) {
        throw new Error(
            `Widget already loaded`)
        );
    }

    let targetElement: HTMLElement;

    for (let i = 0; i < loaderObject.q.length; i++) {
        const item = loaderObject.q[i];
        const methodName = item[0];
        console.log(methodName);
        if (i === 0 && methodName !== 'init') {
            throw new Error(
                `Failed to start Widget`);
        } else if (i !== 0 && methodName === 'init') {
            continue;
        }

        const valueObject = Object.assign(defaultConfig, item[1]);
        const clientID = valueObject.clientID
        console.log("ClientID", clientID)
    }

//rest of the code....

</code>```

I have also tried this. defined a variable clientID outside the for loop and then storing value from inside the for loop. But on printing, I'm getting undefined

```<code>var clientID;
console.log("....last Client ID", clientID)
</code>```
```<code>   const valueObject = Object.assign(defaultConfig, item[1]);
    clientID = valueObject.clientID

</code>```

答:
Your issue is about your variables' scopes. Let's start with a simpler version, without for loop:

default export (a: object) => {
    const variableToExport = a;
}
```
<p>The reason why you can't directly access <code>variableToExport</code> is that it is defined inside the function, and not outside. To deal with it, you have 2 solutions:</p>
<h3>1. Assign to a variable in the outer scope.</h3>
<p>The code would look like:</p>
<p><strong>/!\ Read the text below before using this snipplet /!\</strong></p>
<pre class="lang-js prettyprint-override"><code>export let variableToExport;

default export (a: object) => {
    variableToExport = a;
}
</code>```

Here, you're strictly speaking exporting the variable. Since it's defined outside the function, you can access it outside the function and thus, you can export it. HOWEVER, IT COULD BE A MISTAKE. If you call twice the exported function with different values for a, the variable variableToExport would only have the value corresponding to the second call, and not the first. If the value of variableToExport should not depend  on a, it could be OK, but otherwise it seems risky.

2. Returning the value

Since your function would be called to get the variableToExport, you could return it:

default export (a: object) => {
    const variableToExport = a;
    return variableToExport;
}
```
<p>In case you have multiple things to return, you can build an object to return them all:</p>
<pre class="lang-js prettyprint-override"><code>default export (a: object) => {
    const retValue = {
        "variableToExport": a,
        ... other variables to return
    }
    return retValue;
}
</code>```

Then, you can access it from another module (with or without a destructuring assignment):

import foo from 'path/to/module'

const { variableToExport, otherVariable } = foo(a);
```
<p>This second way is safer than using a "global" variable, as the <code>variableToExport</code> can't have a value that correspond to another call to the function.</p>
<hr />
<p>Now, for the case of your variable in the for loop, you have a similar issue: you can't access to the variable outside the for loop:</p>
<pre class="lang-js prettyprint-override"><code>default export (bar: array) => {
    for (const elem of bar) {
        const clientID = elem.clientID;
    }
    return clientID; // Nope, clientID does not exist here
}
</code>```

To deal with that, the first option works:

default export (bar: array) => {
    let clientID; // Not const, because it will change
    for (const elem of bar) {
        clientID = elem.clientID;
    }
    return clientID;
}
```

This will thus return the last clientID (and since you said you have only one clientID, it should be ok), but it would be a little better of you could get the value of clientID outside the loop, except if you intend on exporting only the last value of clientID.

I hope that, even though you might not understand everything, you understand how to export the client ID you want to export, and that the key words I gave you allows you to easily find what you might need on the internet more easily than these 3 last days. Ask me if anything isn't clear enough, I'll answer when I'll have time

Body:
I'm quite new to programming. I have spend last 3 days trying to figure this out. So any help really appreciate it.

I have access to clientID inside a for loop. (Please look at the last line in the code below). There is only one ClientID which I'm successfully able to print.

I want this client ID to be exported from this module so that I can use it in other modules.

import { Configurations } from './models';

type MethodNames = 'init' | 'event';

export const DEFAULT_NAME = '_hw';

interface LoaderObject {
    q: Array<[MethodNames, {}]>;
}

export default (
    win: Window,
    defaultConfig: Configurations,
    scriptElement: Element | null,
    render: (element: HTMLElement, config: Configurations) => void
) => {

    const instanceName =
        scriptElement?.attributes.getNamedItem('id')?.value ?? DEFAULT_NAME;
    const loaderObject: LoaderObject = win[instanceName];
    if (!loaderObject || !loaderObject.q) {
        throw new Error(
            `Widget didn't find LoaderObject`);
    }

    if (win[`loaded-${instanceName}`]) {
        throw new Error(
            `Widget already loaded`)
        );
    }

    let targetElement: HTMLElement;

    for (let i = 0; i < loaderObject.q.length; i++) {
        const item = loaderObject.q[i];
        const methodName = item[0];
        console.log(methodName);
        if (i === 0 && methodName !== 'init') {
            throw new Error(
                `Failed to start Widget`);
        } else if (i !== 0 && methodName === 'init') {
            continue;
        }

        const valueObject = Object.assign(defaultConfig, item[1]);
        const clientID = valueObject.clientID
        console.log("ClientID", clientID)
    }

//rest of the code....

I have also tried this. defined a variable clientID outside the for loop and then storing value from inside the for loop. But on printing, I'm getting undefined

var clientID;
console.log("....last Client ID", clientID)

   const valueObject = Object.assign(defaultConfig, item[1]);
    clientID = valueObject.clientID

Body:
Your issue is about your variables' scopes. Let's start with a simpler version, without for loop:

default export (a: object) => {
    const variableToExport = a;
}

The reason why you can't directly access variableToExport is that it is defined inside the function, and not outside. To deal with it, you have 2 solutions:

1. Assign to a variable in the outer scope.

The code would look like:

/!\ Read the text below before using this snipplet /!\

export let variableToExport;

default export (a: object) => {
    variableToExport = a;
}

Here, you're strictly speaking exporting the variable. Since it's defined outside the function, you can access it outside the function and thus, you can export it. HOWEVER, IT COULD BE A MISTAKE. If you call twice the exported function with different values for a, the variable variableToExport would only have the value corresponding to the second call, and not the first. If the value of variableToExport should not depend  on a, it could be OK, but otherwise it seems risky.

2. Returning the value

Since your function would be called to get the variableToExport, you could return it:

default export (a: object) => {
    const variableToExport = a;
    return variableToExport;
}

In case you have multiple things to return, you can build an object to return them all:

default export (a: object) => {
    const retValue = {
        "variableToExport": a,
        ... other variables to return
    }
    return retValue;
}

Then, you can access it from another module (with or without a destructuring assignment):

import foo from 'path/to/module'

const { variableToExport, otherVariable } = foo(a);

This second way is safer than using a "global" variable, as the variableToExport can't have a value that correspond to another call to the function.

Now, for the case of your variable in the for loop, you have a similar issue: you can't access to the variable outside the for loop:

default export (bar: array) => {
    for (const elem of bar) {
        const clientID = elem.clientID;
    }
    return clientID; // Nope, clientID does not exist here
}

To deal with that, the first option works:

default export (bar: array) => {
    let clientID; // Not const, because it will change
    for (const elem of bar) {
        clientID = elem.clientID;
    }
    return clientID;
}

This will thus return the last clientID (and since you said you have only one clientID, it should be ok), but it would be a little better of you could get the value of clientID outside the loop, except if you intend on exporting only the last value of clientID.

I hope that, even though you might not understand everything, you understand how to export the client ID you want to export, and that the key words I gave you allows you to easily find what you might need on the internet more easily than these 3 last days. Ask me if anything isn't clear enough, I'll answer when I'll have time


问:
Get the angle and the distance of point from center point
I'm trying to make a color picker and need some help, I need to get an angle of a point from a center point, starting from the top moving to the left, highest value being 1 and the lowest 0, as well as distance between the two points;

I skipped math in high school so I'm at a loss, any help would be appreciated

答:
to find angle between center and the point in radians:

```<code>Math.Atan2(point.y-center.y,point.x-center.x)
</code>```

normalize it:

```<code>Math.Atan2(point.y-center.y,point.x-center.x)/Math.PI/2
</code>```

make it start from top:

```<code>Math.Atan2(point.y-center.y,point.x-center.x)/Math.PI/2+0.25
</code>```

don't let it go below zero:

```<code>(Math.Atan2(point.y-center.y,point.x-center.x)/Math.PI/2+0.25+1)%1
</code>```

invert it so it goes counterclockwise:

```<code>1-(Math.Atan2(point.y-center.y,point.x-center.x)/Math.PI/2+0.25+1)%1
</code>```

you can rewrite it as:

```<code>1-(Math.Atan2(point.y-center.y,point.x-center.x)/2/Math.PI+1.25)%1
</code>```

Body:
to find angle between center and the point in radians:

Math.Atan2(point.y-center.y,point.x-center.x)

normalize it:

Math.Atan2(point.y-center.y,point.x-center.x)/Math.PI/2

make it start from top:

Math.Atan2(point.y-center.y,point.x-center.x)/Math.PI/2+0.25

don't let it go below zero:

(Math.Atan2(point.y-center.y,point.x-center.x)/Math.PI/2+0.25+1)%1

invert it so it goes counterclockwise:

1-(Math.Atan2(point.y-center.y,point.x-center.x)/Math.PI/2+0.25+1)%1

you can rewrite it as:

1-(Math.Atan2(point.y-center.y,point.x-center.x)/2/Math.PI+1.25)%1


问:
HTML Select with disabled Option returns wrong selectedIndex in FireFox
I have a Select with a disabled Option wich is the default selected one:

```<code><select name="select" size="1">
   <option>0</option>
   <option selected disabled>1</option>
   <option>2</option>
   <option>3</option>
   <option>4</option>
</select>
</code>```

If I get the selected, it returns 1. Everything OK.

But if I open the popup and hover with the cursor over another Option (for Example '4')
and Cancel it via ESC or by clicking anywhere else.

The Select input shows the old value 1 but returns on get selected 4.

Example with jsfiddle

It doesn't happen with Chrome only FireFox (4/5)

答:
The following code is ugly, but it does exactly what you want (I think).  Basically, I am intercepting all onChange events, and only processing them if there is a corresponding onClick event that results in a changed value.  ALso note that change events are processed before click events.  EDIT: Just relaized this does not work in chrome, so i added some browser detection code so that it only executes in firefox.

NOTE: The current code would not work if the user had tabbed into the select box and made his changes with the error keys, but the method below can be easily adapted to handle that case as well.  You'd simply need to process key events like arrow up or arrow down or TAB or ENTER in the same way clicks are processed below, but only when the select box had focus.

NOTE 2: Playing with this more, the behavior is very strange.  If you escape out of the select, the onChange event is not triggered, but it is saved up.  If at any later time you click anywhere on the screen the onChange event will be triggered for the value you were hovering over when you escaped, even though that value was actually changed as soon as you escaped.  So this is getting tricky.  I think you may have to handle the 2 cases separately.  One case to handle click aways, and one to handle escape outs (which patrick answered).

It's getting hairy and I see no elegant way to code this.  How about a note to the user next to the text box saying "Your currently selected option, 1, is no longer available."  Then you could have a select box with only the avalable options.

```<code><select name="select" size="1" onChange="handleChange()" onClick="handleClick()" >
  <option>0</option>
  <option selected disabled>1</option>
  <option>2</option>
  <option>3</option>
  <option>4</option>
</select>
<br />

<script>
var initialValue = document.getElementsByName('select')[0].selectedIndex;
var potentialChange;
var processClick;

function handleClick() {

    //ignore this code if not firefox
    if (navigator.userAgent.indexOf("Firefox") === -1)
        return;

    var curVal = document.getElementsByName('select')[0].selectedIndex;
    if (!processClick)
        return;
    // a value change click occured, now we actually process it.
    document.getElementsByName('select')[0].value = potentialChange;
}
function handleChange() {
    // save the potential change, which will be used if a real click was detected
    potentialChange = document.getElementsByName('select')[0].selectedIndex;
    processClick = (potentialChange !== initialValue);
    // undo the attempted change, in case of an escape or page click
    // but only on firefox
    if (navigator.userAgent.indexOf("Firefox")!=-1)
        document.getElementsByName('select')[0].value = initialValue;

    document.getElementsByName('select')[0].value = initialValue;
}
</script>

<a href="javaScript:alert(document.getElementsByName('select')[0].selectedIndex);">getSelected</a>
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I have a Select with a disabled Option wich is the default selected one:

<select name="select" size="1">
   <option>0</option>
   <option selected disabled>1</option>
   <option>2</option>
   <option>3</option>
   <option>4</option>
</select>

If I get the selected, it returns 1. Everything OK.

But if I open the popup and hover with the cursor over another Option (for Example '4')
and Cancel it via ESC or by clicking anywhere else.

The Select input shows the old value 1 but returns on get selected 4.

Example with jsfiddle

It doesn't happen with Chrome only FireFox (4/5)

Body:
The following code is ugly, but it does exactly what you want (I think).  Basically, I am intercepting all onChange events, and only processing them if there is a corresponding onClick event that results in a changed value.  ALso note that change events are processed before click events.  EDIT: Just relaized this does not work in chrome, so i added some browser detection code so that it only executes in firefox.

NOTE: The current code would not work if the user had tabbed into the select box and made his changes with the error keys, but the method below can be easily adapted to handle that case as well.  You'd simply need to process key events like arrow up or arrow down or TAB or ENTER in the same way clicks are processed below, but only when the select box had focus.

NOTE 2: Playing with this more, the behavior is very strange.  If you escape out of the select, the onChange event is not triggered, but it is saved up.  If at any later time you click anywhere on the screen the onChange event will be triggered for the value you were hovering over when you escaped, even though that value was actually changed as soon as you escaped.  So this is getting tricky.  I think you may have to handle the 2 cases separately.  One case to handle click aways, and one to handle escape outs (which patrick answered).

It's getting hairy and I see no elegant way to code this.  How about a note to the user next to the text box saying "Your currently selected option, 1, is no longer available."  Then you could have a select box with only the avalable options.

<select name="select" size="1" onChange="handleChange()" onClick="handleClick()" >
  <option>0</option>
  <option selected disabled>1</option>
  <option>2</option>
  <option>3</option>
  <option>4</option>
</select>
<br />

<script>
var initialValue = document.getElementsByName('select')[0].selectedIndex;
var potentialChange;
var processClick;

function handleClick() {

    //ignore this code if not firefox
    if (navigator.userAgent.indexOf("Firefox") === -1)
        return;

    var curVal = document.getElementsByName('select')[0].selectedIndex;
    if (!processClick)
        return;
    // a value change click occured, now we actually process it.
    document.getElementsByName('select')[0].value = potentialChange;
}
function handleChange() {
    // save the potential change, which will be used if a real click was detected
    potentialChange = document.getElementsByName('select')[0].selectedIndex;
    processClick = (potentialChange !== initialValue);
    // undo the attempted change, in case of an escape or page click
    // but only on firefox
    if (navigator.userAgent.indexOf("Firefox")!=-1)
        document.getElementsByName('select')[0].value = initialValue;

    document.getElementsByName('select')[0].value = initialValue;
}
</script>

<a href="javaScript:alert(document.getElementsByName('select')[0].selectedIndex);">getSelected</a>


问:
Getting a NoSuchElementException when trying to find a text box inside a Modal Dialog box while using Python Selenium
I'm trying to input text into a textbox that's part of a popup dialog page, which I think is a modal dialogue box.

After I successfully click on a button on the page with this code:

```<code>driver.find_element_by_xpath('//*[@id="get_content"]/div[1]/div/div[2]/h3').click()
</code>```

I get a dialog box with some textboxes. When I try to input text into one of the textboxes with the following code:

```<code>driver.find_element_by_xpath('//*[@id="textbox"]').send_keys("Update Cases")
</code>```

I get the following error:

```<code>NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"//*[@id="textbox"]"}
</code>```

I tried clicking on the popup dialog box:

```<code>driver.find_element_by_xpath('//*[@id="popup_dialog"]').click()
</code>```

Only to get this error:

```<code>ElementNotInteractableException: element not interactable: element has zero size
</code>```

I tried putting this line before the code above to switch to the active screen:

driver.switch_to.active_element

The line didn't generate any errors. But "method":"xpath","selector":"//*[@id="textbox"]" still yielded NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"//*[@id="textbox"]"}.

I tried:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH,'//*[@id="textbox"]'))).send_keys('Update Cases')
I got a TimeoutException.

The following is the outer HTML for the popup dialog box.

The page is internal, but the following is partial outer HTML code for the

```<code><div id="popup_dialog"><div class="popup_dialog create_request_dialog"><div class="item_header has_icon"><div class="item_icon"><img src="/servicedesk/customershim/secure/viewavatar?...<div class="popup_dialog_cover"></div></div>
</code>```

Thus far, none of the above has worked. Any suggestions?

答:
I see no elements with id="textbox" in HTML you presenting here.

As about the

driver.find_element_by_xpath('//*[@id="popup_dialog"]').click()
```
<p>Try adding a wait condition there, something like</p>
<pre class="lang-py prettyprint-override"><code> WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH,'//*[@id="popup_dialog"]'))).click()
</code>```

We can only guess about the correct solution here since we can't see and debug the page you are working on

Body:
I'm trying to input text into a textbox that's part of a popup dialog page, which I think is a modal dialogue box.

After I successfully click on a button on the page with this code:

driver.find_element_by_xpath('//*[@id="get_content"]/div[1]/div/div[2]/h3').click()

I get a dialog box with some textboxes. When I try to input text into one of the textboxes with the following code:

driver.find_element_by_xpath('//*[@id="textbox"]').send_keys("Update Cases")

I get the following error:

NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"//*[@id="textbox"]"}

I tried clicking on the popup dialog box:

driver.find_element_by_xpath('//*[@id="popup_dialog"]').click()

Only to get this error:

ElementNotInteractableException: element not interactable: element has zero size

I tried putting this line before the code above to switch to the active screen:

driver.switch_to.active_element

The line didn't generate any errors. But "method":"xpath","selector":"//*[@id="textbox"]" still yielded NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"//*[@id="textbox"]"}.

I tried:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH,'//*[@id="textbox"]'))).send_keys('Update Cases')
I got a TimeoutException.

The following is the outer HTML for the popup dialog box.

The page is internal, but the following is partial outer HTML code for the

<img src="/servicedesk/customershim/secure/viewavatar?...

Thus far, none of the above has worked. Any suggestions?

Body:
I see no elements with id="textbox" in HTML you presenting here.

As about the

driver.find_element_by_xpath('//*[@id="popup_dialog"]').click()

Try adding a wait condition there, something like

 WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH,'//*[@id="popup_dialog"]'))).click()

We can only guess about the correct solution here since we can't see and debug the page you are working on


问:
How to have two build flavors inherit from a root flavor in Android Studio?
I used to have the following project flavors:

Apple

Orange

Originally the only difference was the applicationId/packageName. Now there is a single java file that is different. A custom ArrayAdapter to be exact. The solution was to create src/Apple and src/Orange and both inherit from src/main. I removed the java file from src/main and put a copy into src/Apple and src/Orange and modified it appropriately. All was good in the world.

Fast forward a few weeks, now there are about 10 java files that differ between Apple and Orange. Again... no big deal. Easy to handle. Separate java files in src/Apple and src/Orange.

Fast forward to today. I need to modify things up a bit, because I want to have a free and premium version of each. The free and premium versions only differ by a URL. I was going to simply create the new types called:

AppleFree

ApplePremium

OrangeFree

OrangePremium

I have a dilema though. Since now src/Apple and src/Orange have 10 different files that have been changed... if I change any java file in AppleFree I have to make sure I do the same in ApplePremium. I'm kind of at a crossroads and hope my question makes sense at this point. I have come up with three possible solutions, but I'm not sure how I would implement them/what would be the correct approach/the solution is not what I want.

Solution 1:

Use an if statement
if (BuildConfig.FLAVOR==appleFree) {//use free Url} else {// use premium url}

Issue: Both Urls are technically compiled into the apk. I do not want this.

Solution 2:

Have src/AppleFree and src/ApplePremium inherit from an src/Apple parent directory somehow.

Issue: Not sure how I would do this.

Solution 3:

Add the free and premium url right in build.gradle like so?

```<code>    productFlavors {
            appleFree {
                applicationId "com.example.apple.free"
                versionName "1.0"
                url "http://freeurl.com"
                versionCode 1
            }
            applePremium {
                applicationId "com.example.apple.premium"
                versionName "1.0"
                url "http://premiumurl.com"
                versionCode 1
            }
            orangeFree {
                applicationId "com.example.orange.free"
                versionName "1.0"
                versionCode 1
                url "http://freeurl.com"

            }
            orangePremium {
                applicationId "com.example.orange.premium"
                url "http://premiumurl.com"
                versionName "1.0"
                versionCode 1

            }
        }
</code>```

Issue: Not sure how to make that work.

Any tips are helpful.

EDIT:

Final Solution?

```<code>flavorGroups 'fruit', 'paid'

productFlavors {
    apple {
        flavorGroup 'fruit'
    }
    orange {
        flavorGroup 'fruit'
    }
    free {
        flavorGroup 'paid'
    }
    premium {
        flavorGroup 'paid'
    }
    appleFree {
        applicationId "com.example.apple.free"
        versionName "1.0"
        buildConfigField 'String', 'BASE_URL', 'http://freeurl.com'
        versionCode 1
    }
    applePremium {
        applicationId "com.example.apple.premium"
        versionName "1.0"
        buildConfigField 'String', 'BASE_URL', 'http://premiumurl.com'
        versionCode 1
    }
    orangeFree {
        applicationId "com.example.orange.free"
        versionName "1.0"
        versionCode 1
        buildConfigField 'String', 'BASE_URL', 'http://freeurl.com'
    }
    orangePremium {
        applicationId "com.example.orange.premium"
        buildConfigField 'String', 'BASE_URL', 'http://premiumurl.com'
        versionName "1.0"
        versionCode 1
    }
    }
</code>```

答:
Here's how I implemented product flavors inheritance.

stageLt (extends baseLt) - app for Lithuania using stage API

productionLt (extends baseLt) - app for Lithuania using production API

stagePl (extends basePl) - app for Poland using stage API

stagePl (extends basePl) - app for Poland using production API

```<code>android {
    flavorDimensions "default"

    productFlavors {
        def API_URL = "API_URL"
        def PHONE_NUMBER_PREFIX = "PHONE_NUMBER_PREFIX"
        def IBAN_HINT = "IBAN_HINT"

        baseLt {
            buildConfigField "String", PHONE_NUMBER_PREFIX, '"+370"'
            resValue "string", IBAN_HINT, "LT00 0000 0000 0000 0000"
        }
        basePl {
            buildConfigField "String", PHONE_NUMBER_PREFIX, '"+48"'
            resValue "string", IBAN_HINT, "PL00 0000 0000 0000 0000 0000 0000"
        }

        stageLt {
            dimension "default"
            applicationId "lt.app.stage"
            buildConfigField "String", API_URL, '"https://www.limetorrents.pro/"'
        }
        productionLt {
            dimension "default"
            applicationId "lt.app"
            buildConfigField "String", API_URL, '"https://yts.mx/"'
        }

        stagePl {
            dimension "default"
            applicationId "pl.app.stage"
            buildConfigField "String", API_URL, '"https://1337x.to/"'
        }
        productionPl {
            dimension "default"
            applicationId "pl.app"
            buildConfigField "String", API_URL, '"http://programming-motherfucker.com/"'
        }
    }

    // base product flavors will not show up in 'Build Variants' view.
    variantFilter { variant ->
        if (variant.name.startsWith("base")) {
            setIgnore(true)
        }
    }
}

void setupProductFlavor(baseFlavor, flavor) {
    flavor.buildConfigFields.putAll(baseFlavor.buildConfigFields)
    flavor.resValues.putAll(baseFlavor.resValues)
    flavor.manifestPlaceholders.putAll(baseFlavor.manifestPlaceholders)
    // Note that other product flavor properties ('proguardFiles', 'signingConfig', etc.) are not merged.
    // E.g. if in base product flavor you declare 'signingConfig', it will not be copied to child product flavor.
    // Implement if needed.
}

// Merge 'parent product flavors' with 'child product flavors'
setupProductFlavor(android.productFlavors.baseLt, android.productFlavors.stageLt)
setupProductFlavor(android.productFlavors.baseLt, android.productFlavors.productionLt)
setupProductFlavor(android.productFlavors.basePl, android.productFlavors.stagePl)
setupProductFlavor(android.productFlavors.basePl, android.productFlavors.productionPl)
</code>```

Body:
I used to have the following project flavors:

Apple

Orange

Originally the only difference was the applicationId/packageName. Now there is a single java file that is different. A custom ArrayAdapter to be exact. The solution was to create src/Apple and src/Orange and both inherit from src/main. I removed the java file from src/main and put a copy into src/Apple and src/Orange and modified it appropriately. All was good in the world.

Fast forward a few weeks, now there are about 10 java files that differ between Apple and Orange. Again... no big deal. Easy to handle. Separate java files in src/Apple and src/Orange.

Fast forward to today. I need to modify things up a bit, because I want to have a free and premium version of each. The free and premium versions only differ by a URL. I was going to simply create the new types called:

AppleFree

ApplePremium

OrangeFree

OrangePremium

I have a dilema though. Since now src/Apple and src/Orange have 10 different files that have been changed... if I change any java file in AppleFree I have to make sure I do the same in ApplePremium. I'm kind of at a crossroads and hope my question makes sense at this point. I have come up with three possible solutions, but I'm not sure how I would implement them/what would be the correct approach/the solution is not what I want.

Solution 1:

Use an if statement
if (BuildConfig.FLAVOR==appleFree) {//use free Url} else {// use premium url}

Issue: Both Urls are technically compiled into the apk. I do not want this.

Solution 2:

Have src/AppleFree and src/ApplePremium inherit from an src/Apple parent directory somehow.

Issue: Not sure how I would do this.

Solution 3:

Add the free and premium url right in build.gradle like so?

    productFlavors {
            appleFree {
                applicationId "com.example.apple.free"
                versionName "1.0"
                url "http://freeurl.com"
                versionCode 1
            }
            applePremium {
                applicationId "com.example.apple.premium"
                versionName "1.0"
                url "http://premiumurl.com"
                versionCode 1
            }
            orangeFree {
                applicationId "com.example.orange.free"
                versionName "1.0"
                versionCode 1
                url "http://freeurl.com"

            }
            orangePremium {
                applicationId "com.example.orange.premium"
                url "http://premiumurl.com"
                versionName "1.0"
                versionCode 1

            }
        }

Issue: Not sure how to make that work.

Any tips are helpful.

EDIT:

Final Solution?

flavorGroups 'fruit', 'paid'

productFlavors {
    apple {
        flavorGroup 'fruit'
    }
    orange {
        flavorGroup 'fruit'
    }
    free {
        flavorGroup 'paid'
    }
    premium {
        flavorGroup 'paid'
    }
    appleFree {
        applicationId "com.example.apple.free"
        versionName "1.0"
        buildConfigField 'String', 'BASE_URL', 'http://freeurl.com'
        versionCode 1
    }
    applePremium {
        applicationId "com.example.apple.premium"
        versionName "1.0"
        buildConfigField 'String', 'BASE_URL', 'http://premiumurl.com'
        versionCode 1
    }
    orangeFree {
        applicationId "com.example.orange.free"
        versionName "1.0"
        versionCode 1
        buildConfigField 'String', 'BASE_URL', 'http://freeurl.com'
    }
    orangePremium {
        applicationId "com.example.orange.premium"
        buildConfigField 'String', 'BASE_URL', 'http://premiumurl.com'
        versionName "1.0"
        versionCode 1
    }
    }

Body:
Here's how I implemented product flavors inheritance.

stageLt (extends baseLt) - app for Lithuania using stage API

productionLt (extends baseLt) - app for Lithuania using production API

stagePl (extends basePl) - app for Poland using stage API

stagePl (extends basePl) - app for Poland using production API

android {
    flavorDimensions "default"

    productFlavors {
        def API_URL = "API_URL"
        def PHONE_NUMBER_PREFIX = "PHONE_NUMBER_PREFIX"
        def IBAN_HINT = "IBAN_HINT"

        baseLt {
            buildConfigField "String", PHONE_NUMBER_PREFIX, '"+370"'
            resValue "string", IBAN_HINT, "LT00 0000 0000 0000 0000"
        }
        basePl {
            buildConfigField "String", PHONE_NUMBER_PREFIX, '"+48"'
            resValue "string", IBAN_HINT, "PL00 0000 0000 0000 0000 0000 0000"
        }

        stageLt {
            dimension "default"
            applicationId "lt.app.stage"
            buildConfigField "String", API_URL, '"https://www.limetorrents.pro/"'
        }
        productionLt {
            dimension "default"
            applicationId "lt.app"
            buildConfigField "String", API_URL, '"https://yts.mx/"'
        }

        stagePl {
            dimension "default"
            applicationId "pl.app.stage"
            buildConfigField "String", API_URL, '"https://1337x.to/"'
        }
        productionPl {
            dimension "default"
            applicationId "pl.app"
            buildConfigField "String", API_URL, '"http://programming-motherfucker.com/"'
        }
    }

    // base product flavors will not show up in 'Build Variants' view.
    variantFilter { variant ->
        if (variant.name.startsWith("base")) {
            setIgnore(true)
        }
    }
}

void setupProductFlavor(baseFlavor, flavor) {
    flavor.buildConfigFields.putAll(baseFlavor.buildConfigFields)
    flavor.resValues.putAll(baseFlavor.resValues)
    flavor.manifestPlaceholders.putAll(baseFlavor.manifestPlaceholders)
    // Note that other product flavor properties ('proguardFiles', 'signingConfig', etc.) are not merged.
    // E.g. if in base product flavor you declare 'signingConfig', it will not be copied to child product flavor.
    // Implement if needed.
}

// Merge 'parent product flavors' with 'child product flavors'
setupProductFlavor(android.productFlavors.baseLt, android.productFlavors.stageLt)
setupProductFlavor(android.productFlavors.baseLt, android.productFlavors.productionLt)
setupProductFlavor(android.productFlavors.basePl, android.productFlavors.stagePl)
setupProductFlavor(android.productFlavors.basePl, android.productFlavors.productionPl)


问:
Angular Http Observable doesn't update
Hey Guys i wrote a little backend which returns some data. Now i want to fetch this data with Angular Http and show new values when i post them in the backend. So the first thing that came to my mind were Observables but currently i can fetch the data onInit but when Posting new Data to the Backend (currently just via Postman) the Fetched data wont update. So if this is the wrong approach tell me how to do this please. Below is my code i used so far:

App Component:

```<code>import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import 'rxjs/add/operator/map';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import {WeaponServiceService} from './weapon-service.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent implements OnInit {
  weaponTypesarr: IweaponsTypes [] = [
    {name: 'Nahkampf', value: 'melee'},
    {name: 'Fernkampf', value: 'ranged'},
    {name: 'Spezial', value: 'special'},
  ];
  meleeTypesarr: IweaponsTypes [] = [
    {name: 'Klingenwaffen', value: 'klinge'},
    {name: 'Messer', value: 'messer'},
    {name: 'Dolche', value: 'dolch'},
    {name: 'Äxte/Beile', value: 'axt'},
    {name: 'Speere/Stäbe', value: 'speer'},
    {name: 'Stumpfe Hiebwaffen', value: 'stumpf'}
  ];
  rangedTypesarr: IweaponsTypes [] = [
    {name: 'Bogen', value: 'bogen'},
    {name: 'Armbrust', value: 'armbrust'},
    {name: 'Wurfwaffe', value: 'wurfwaffe'},
    {name: 'kleine Schusswaffe', value: 'gun-litte'},
    {name: 'große Schusswaffe', value: 'gun-big'}
  ];
  specialTypesarr: IweaponsTypes [] = [
    {name: 'Exotische Waffen', value: 'exotics'},
    {name: 'Granaten und Exoplosive', value: 'grenade'}
  ];
  rForm: FormGroup;
  post: any;
  weaponName = '';
  weaponType= '';
  impairment= '';
  special= '';
  results: Observable<any>;
  constructor(private fb: FormBuilder , private weaponService: WeaponServiceService) {
    this.rForm = fb.group({
      'weaponName' : [null, Validators.required],
      'weaponType': [null, Validators.required],
      'impairment': [null, Validators.required],
      'special': [null, Validators.required]
    });
  }
  ngOnInit() {
     this.results = this.weaponService.getWeapons();
     this.results.subscribe(data => {console.log(data); });
  }

  generateWeapon(weaponData) {
    this.weaponName = weaponData.weaponName;
    this.weaponType = weaponData.weaponType;
    this.impairment = weaponData.impairment;
    this.special = weaponData.special;
    console.log(weaponData);
  }

}

export interface IweaponsTypes {
  name: string;
  value: string;
}
</code>```

WeaponServiceService (didnt knew it calls it service by its own :D):

```<code>import { Injectable } from '@angular/core';
import {HttpClient} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class WeaponServiceService {

  constructor( private http: HttpClient) { }

  getWeapons() {
    return this.http.get('http://192.168.178.48:3000/getWeapons').map(data => {
      return(data);
    },
    err => {
      console.log(err);
    }
  );
  }

  createWeapon(weaponData2: any) {
    return this.http.post('http://192.168.178.48:3000/createWeapon', weaponData2)
    .map(
      res => {
        console.log(res);
      },
      err => {
        console.log(err);
      }
    );
  }
}
</code>```

Module:

```<code>import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import {NgbModule} from '@ng-bootstrap/ng-bootstrap';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';
import {WeaponServiceService} from './weapon-service.service';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpClientModule,
    ReactiveFormsModule,
    NgbModule.forRoot()
  ],
  providers: [WeaponServiceService],
  bootstrap: [AppComponent]
})
export class AppModule { }
</code>```

and last but not least the corresponding HTML but currently i just try to log all the values.

```<code><div *ngIf="!name; else forminfo">
  <form [formGroup]="rForm" (ngSubmit)="generateWeapon(rForm.value)">
        <h1>Generate Weapon</h1>
        <label for="WeaponName">WeaponName</label>
        <input  class="form-control" type="text" name="weaponName" formControlName="weaponName" id="WeaponName">
        <div class="form-group">
            <label for="WeaponGroup">Weapon Group</label>
                <select class="form-control" #weaponTypeSelektor formControlName="weaponType" id="WeaponGroup">
                    <option> Select a Type</option>
                    <option *ngFor="let types of weaponTypesarr" [value]="types.value">{{types.name}}</option>
                </select>
          </div>
          <div class="form-group" *ngIf="weaponTypeSelektor.value == 'melee'">
              <label for="WeaponTypeMelee">Weapon Type</label>
                  <select class="form-control" formControlName="weaponType" id="WeaponTypeMelee">
                      <option *ngFor="let types of meleeTypesarr" [value]="types.value">{{types.name}}</option>
                  </select>
            </div>
            <div class="form-group" *ngIf="weaponTypeSelektor.value == 'ranged'">
                <label for="WeaponTypeRanged">Weapon Type</label>
                    <select class="form-control" formControlName="weaponType" id="WeaponTypeRanged">
                        <option *ngFor="let types of rangedTypesarr" [value]="types.value">{{types.name}}</option>
                    </select>
              </div>
              <div class="form-group" *ngIf="weaponTypeSelektor.value == 'special'">
                  <label for="WeaponTypeSpecial">Weapon Type</label>
                      <select class="form-control" formControlName="weaponType" id="WeaponTypeSpecial">
                          <option *ngFor="let types of specialTypesarr" [value]="types.value">{{types.name}}</option>
                      </select>
                </div>
        <label for="impairment">Beeinträchtigung</label>
        <input class="form-control" type="text" name="Beeinträchtigung" formControlName="impairment" value="" id="impairment">
        <label for="special">Spezial</label>
        <input class="form-control" type="text" name="Spezial" formControlName="special" value="" id="special">
        <br><br>
        <input type="submit" class="btn btn-primary" value="Submit Form" [disabled]="!rForm.valid">
  </form>

  <div  *ngFor="let item of results | async"> {{item.weaponName}} </div>
</div>

<ng-template #forminfo>
  <div class="form-container">
    <div class="row columns">
        <h1>{{ name }}</h1>

        <p>{{ weaponType }}</p>
    </div>
  </div>
</ng-template>
</code>```

So just to be clear. AppComponent starts and fetched  initial data. I post Data into the Db with postman. App Component doesn't recognize new Value.

答:
Tested on:

Angular CLI: 13.1.4

Node: 17.3.0

Package Manager: npm 8.3.0

I know I don't have the best answer but one which works (at least).
Maybe it helps someone to continue further   ;-)

I fetched the data once in the component's ngOnInit as well as in a function which pulls the database data after a defined interval/time has passed.

  data: any;
  baseUrl = 'foo_URL';
  fetchInterval: 3000;   // 3 Seconds

  constructor(private http: HttpClient) {
  }

  // First Fetch
  ngOnInit(): void {
    this.http.get(this.baseUrl)
    .pipe(takeUntil(this.destroy$))
    .subscribe((fooData) => {
      this.data = fooData;
    })
  }

  // Interval Fetch
  setInterval: any = setInterval(() => {
    this.http.get(this.baseUrl)
    .pipe(takeUntil(this.destroy$))
    .subscribe((fooData) => {
      // Compare for view update
      if (JSON.stringify(fooData) !== JSON.stringify(this.data)) {
        console.log('New stuff -> update view')
        this.data = fooData;
      }
    });
  }, fetchInterval)

  // Shield Memory Leakeage after Component is deleted
  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }
```

This is generally a bad approach as ..

.. data is pulled although there is no update the data.

.. data may be pushed towards the view without any need (fixed).

.. the interval is (mostly) barely adjustable to fit the need of both sides, Client & Server.

It is recommended to at least check changes in the data before updating the view with the same data.
Maybe even offer an API which only serves a checksum before pulling the whole dataset.

Last:
The more advanced solution would be a two-way-binding.
Once an API is called which changes the data, angular gets an update for the backend. For this kind of solution you might want to take a look at socket.io ... ;-)

Title: Angular Http Observable doesn't update

Body:
Hey Guys i wrote a little backend which returns some data. Now i want to fetch this data with Angular Http and show new values when i post them in the backend. So the first thing that came to my mind were Observables but currently i can fetch the data onInit but when Posting new Data to the Backend (currently just via Postman) the Fetched data wont update. So if this is the wrong approach tell me how to do this please. Below is my code i used so far:

App Component:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import 'rxjs/add/operator/map';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import {WeaponServiceService} from './weapon-service.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent implements OnInit {
  weaponTypesarr: IweaponsTypes [] = [
    {name: 'Nahkampf', value: 'melee'},
    {name: 'Fernkampf', value: 'ranged'},
    {name: 'Spezial', value: 'special'},
  ];
  meleeTypesarr: IweaponsTypes [] = [
    {name: 'Klingenwaffen', value: 'klinge'},
    {name: 'Messer', value: 'messer'},
    {name: 'Dolche', value: 'dolch'},
    {name: 'Äxte/Beile', value: 'axt'},
    {name: 'Speere/Stäbe', value: 'speer'},
    {name: 'Stumpfe Hiebwaffen', value: 'stumpf'}
  ];
  rangedTypesarr: IweaponsTypes [] = [
    {name: 'Bogen', value: 'bogen'},
    {name: 'Armbrust', value: 'armbrust'},
    {name: 'Wurfwaffe', value: 'wurfwaffe'},
    {name: 'kleine Schusswaffe', value: 'gun-litte'},
    {name: 'große Schusswaffe', value: 'gun-big'}
  ];
  specialTypesarr: IweaponsTypes [] = [
    {name: 'Exotische Waffen', value: 'exotics'},
    {name: 'Granaten und Exoplosive', value: 'grenade'}
  ];
  rForm: FormGroup;
  post: any;
  weaponName = '';
  weaponType= '';
  impairment= '';
  special= '';
  results: Observable<any>;
  constructor(private fb: FormBuilder , private weaponService: WeaponServiceService) {
    this.rForm = fb.group({
      'weaponName' : [null, Validators.required],
      'weaponType': [null, Validators.required],
      'impairment': [null, Validators.required],
      'special': [null, Validators.required]
    });
  }
  ngOnInit() {
     this.results = this.weaponService.getWeapons();
     this.results.subscribe(data => {console.log(data); });
  }

  generateWeapon(weaponData) {
    this.weaponName = weaponData.weaponName;
    this.weaponType = weaponData.weaponType;
    this.impairment = weaponData.impairment;
    this.special = weaponData.special;
    console.log(weaponData);
  }

}

export interface IweaponsTypes {
  name: string;
  value: string;
}

WeaponServiceService (didnt knew it calls it service by its own :D):

import { Injectable } from '@angular/core';
import {HttpClient} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class WeaponServiceService {

  constructor( private http: HttpClient) { }

  getWeapons() {
    return this.http.get('http://192.168.178.48:3000/getWeapons').map(data => {
      return(data);
    },
    err => {
      console.log(err);
    }
  );
  }

  createWeapon(weaponData2: any) {
    return this.http.post('http://192.168.178.48:3000/createWeapon', weaponData2)
    .map(
      res => {
        console.log(res);
      },
      err => {
        console.log(err);
      }
    );
  }
}

Module:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import {NgbModule} from '@ng-bootstrap/ng-bootstrap';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';
import {WeaponServiceService} from './weapon-service.service';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpClientModule,
    ReactiveFormsModule,
    NgbModule.forRoot()
  ],
  providers: [WeaponServiceService],
  bootstrap: [AppComponent]
})
export class AppModule { }

and last but not least the corresponding HTML but currently i just try to log all the values.

  <form [formGroup]="rForm" (ngSubmit)="generateWeapon(rForm.value)">

Generate Weapon

        WeaponName
        <input  class="form-control" type="text" name="weaponName" formControlName="weaponName" id="WeaponName">

            Weapon Group
                <select class="form-control" #weaponTypeSelektor formControlName="weaponType" id="WeaponGroup">
                    <option> Select a Type</option>
                    <option *ngFor="let types of weaponTypesarr" [value]="types.value">{{types.name}}</option>
                </select>

              Weapon Type
                  <select class="form-control" formControlName="weaponType" id="WeaponTypeMelee">
                      <option *ngFor="let types of meleeTypesarr" [value]="types.value">{{types.name}}</option>
                  </select>

                Weapon Type
                    <select class="form-control" formControlName="weaponType" id="WeaponTypeRanged">
                        <option *ngFor="let types of rangedTypesarr" [value]="types.value">{{types.name}}</option>
                    </select>

                  Weapon Type
                      <select class="form-control" formControlName="weaponType" id="WeaponTypeSpecial">
                          <option *ngFor="let types of specialTypesarr" [value]="types.value">{{types.name}}</option>
                      </select>

        Beeinträchtigung
        <input class="form-control" type="text" name="Beeinträchtigung" formControlName="impairment" value="" id="impairment">
        Spezial
        <input class="form-control" type="text" name="Spezial" formControlName="special" value="" id="special">

        <input type="submit" class="btn btn-primary" value="Submit Form" [disabled]="!rForm.valid">
  </form>

 {{item.weaponName}}

<ng-template #forminfo>

{{ name }}

{{ weaponType }}

</ng-template>

So just to be clear. AppComponent starts and fetched  initial data. I post Data into the Db with postman. App Component doesn't recognize new Value.

Body:
Tested on:

Angular CLI: 13.1.4

Node: 17.3.0

Package Manager: npm 8.3.0

I know I don't have the best answer but one which works (at least).
Maybe it helps someone to continue further   ;-)

I fetched the data once in the component's ngOnInit as well as in a function which pulls the database data after a defined interval/time has passed.

  data: any;
  baseUrl = 'foo_URL';
  fetchInterval: 3000;   // 3 Seconds

  constructor(private http: HttpClient) {
  }

  // First Fetch
  ngOnInit(): void {
    this.http.get(this.baseUrl)
    .pipe(takeUntil(this.destroy$))
    .subscribe((fooData) => {
      this.data = fooData;
    })
  }

  // Interval Fetch
  setInterval: any = setInterval(() => {
    this.http.get(this.baseUrl)
    .pipe(takeUntil(this.destroy$))
    .subscribe((fooData) => {
      // Compare for view update
      if (JSON.stringify(fooData) !== JSON.stringify(this.data)) {
        console.log('New stuff -> update view')
        this.data = fooData;
      }
    });
  }, fetchInterval)

  // Shield Memory Leakeage after Component is deleted
  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }

This is generally a bad approach as ..

.. data is pulled although there is no update the data.

.. data may be pushed towards the view without any need (fixed).

.. the interval is (mostly) barely adjustable to fit the need of both sides, Client & Server.

It is recommended to at least check changes in the data before updating the view with the same data.
Maybe even offer an API which only serves a checksum before pulling the whole dataset.

Last:
The more advanced solution would be a two-way-binding.
Once an API is called which changes the data, angular gets an update for the backend. For this kind of solution you might want to take a look at socket.io ... ;-)


问:
Unexpected result when using list.append(). What am I doing wrong?
I can't understand the following two examples of behaviour of list.append() in Python:

```<code>list_1 = ['A', 'B']
list_2 = ['C', 'D']

copy_l1 = list_1
copy_l1.append(list_2)
</code>```

Example

```<code>print(copy_l1)
</code>```

result: ['A', 'B', ['C', 'D']]

expected: ['A', 'B', 'C', 'D'].

I kind of understand this, but how to get the expected result?

Example

```<code>print(list_1)
</code>```

result: ['A', 'B', ['C', 'D']]

expected: ['A', 'B'].

This is the most puzzling for me. Why does copy_l1.append(list_2) also affect list_1? Due to my backgound in C, this looks to me like I'm working on pointers, but I gather that should not be the case. What means?

答:
```<code>list_1 = ['A', 'B']
list_2 = ['C', 'D']

copy_l1 = list_1
copy_l1.extend( list_2 )
#or
copy_l1+=list_2
</code>```

Body:
I can't understand the following two examples of behaviour of list.append() in Python:

list_1 = ['A', 'B']
list_2 = ['C', 'D']

copy_l1 = list_1
copy_l1.append(list_2)

Example

print(copy_l1)

result: ['A', 'B', ['C', 'D']]

expected: ['A', 'B', 'C', 'D'].

I kind of understand this, but how to get the expected result?

Example

print(list_1)

result: ['A', 'B', ['C', 'D']]

expected: ['A', 'B'].

This is the most puzzling for me. Why does copy_l1.append(list_2) also affect list_1? Due to my backgound in C, this looks to me like I'm working on pointers, but I gather that should not be the case. What means?