问:
Why does a locally scoped variable that hasn't been defined reference the instance variable of the same name?
I came across an odd bug in my code that revealed an interesting behavior of ruby.  Hopefully someone can explain why it behaves this way.

I had a class with an instance variable @foo and a method that referenced a locally scoped variable foo.  I refactored part of the method out accidentally leaving the reference to foo; the variable no longer defined in the scope.  It ended up pointing to @foo instead.  Changing foo made changes to @foo and vice versa.

Simplified version:
EDIT : added ImOutOfNames.

```<code>class ImOutOfNames
    attr_accessor :foo # the culprit!
end

class Bar < ImOutOfNames
    def initialize
        @foo = "that is a tasty burger"
    end

    def bar_method_1
        foo = "Come on Yolanda, whats Fonzie like?"
        bar_method_2
    end

    def bar_method_2
        puts foo
    end
end
</code>```

And the output of bar_method_1 and bar_method_2 was "that is a tasty burger".  I was expecting there to be an error, for example running the above code gets

```<code>NameError: undefined local variable or method
</code>```

I even had a more senior developer come take a  look and he was somewhat baffled and confirmed the behavior.

Is this an expected behavior and I misunderstood how @variables work or is there something wrong?

答:
Your previous buggy code probably at an attr_accessor  definition that created a method foo that accessed to your instance variable,

You can have the same behavior if your code is like this:

```<code>class Bar

  attr_accessor :foo

  def initialize
    @foo = "that is a tasty burger"
  end

  def bar_method_1
    foo = "Come on Yolanda, whats Fonzie like?"
    bar_method_2
  end

  def bar_method_2
    puts foo
  end
end
</code>```

The attr_accessor call defines two methods in your object;

```<code>def foo
  @foo
end

def foo=(value)
  @foo = value
end
</code>```

So in your case, when no local variable was defined, the method was used, but as you did not call attr_accessor in this example you posted the method was not defined and there was no local variable to use on bar_method_2 so the call fails.

Body:
I came across an odd bug in my code that revealed an interesting behavior of ruby.  Hopefully someone can explain why it behaves this way.

I had a class with an instance variable @foo and a method that referenced a locally scoped variable foo.  I refactored part of the method out accidentally leaving the reference to foo; the variable no longer defined in the scope.  It ended up pointing to @foo instead.  Changing foo made changes to @foo and vice versa.

Simplified version:
EDIT : added ImOutOfNames.

class ImOutOfNames
    attr_accessor :foo # the culprit!
end

class Bar < ImOutOfNames
    def initialize
        @foo = "that is a tasty burger"
    end

    def bar_method_1
        foo = "Come on Yolanda, whats Fonzie like?"
        bar_method_2
    end

    def bar_method_2
        puts foo
    end
end

And the output of bar_method_1 and bar_method_2 was "that is a tasty burger".  I was expecting there to be an error, for example running the above code gets

NameError: undefined local variable or method

I even had a more senior developer come take a  look and he was somewhat baffled and confirmed the behavior.

Is this an expected behavior and I misunderstood how @variables work or is there something wrong?

Body:
Your previous buggy code probably at an attr_accessor  definition that created a method foo that accessed to your instance variable,

You can have the same behavior if your code is like this:

class Bar

  attr_accessor :foo

  def initialize
    @foo = "that is a tasty burger"
  end

  def bar_method_1
    foo = "Come on Yolanda, whats Fonzie like?"
    bar_method_2
  end

  def bar_method_2
    puts foo
  end
end

The attr_accessor call defines two methods in your object;

def foo
  @foo
end

def foo=(value)
  @foo = value
end

So in your case, when no local variable was defined, the method was used, but as you did not call attr_accessor in this example you posted the method was not defined and there was no local variable to use on bar_method_2 so the call fails.


来源: stackexchange

问:
Count and Mark TRUE if Range in a Single Row Contains 3 or More Instances of TRUE
So, I'm wanting to count the number of cells in a row (U5:X5) that contain TRUE, and if the range contains 3 or more instances of TRUE, I want to mark the cell TRUE, showing that yes, there are 3 or more instances of TRUE in the range.

What I have so far is not working...

```<code>=IF(COUNTIF(U5:X5,"TRUE") >= 3,"TRUE","")
</code>```

Here's a Google Sheet that you can edit.

Thanks for your help!

答:
Use:

```<code>=COUNTIF(A5:F5,TRUE)>=3
</code>```

ContentLicense: CC BY-SA 4.0

Body:
So, I'm wanting to count the number of cells in a row (U5:X5) that contain TRUE, and if the range contains 3 or more instances of TRUE, I want to mark the cell TRUE, showing that yes, there are 3 or more instances of TRUE in the range.

What I have so far is not working...

=IF(COUNTIF(U5:X5,"TRUE") >= 3,"TRUE","")

Here's a Google Sheet that you can edit.

Thanks for your help!

Body:
Use:

=COUNTIF(A5:F5,TRUE)>=3


问:
How to handle Dead Letter Queues in Amazon SQS?
I am using event-driven architecture for one of my projects. Amazon Simple Queue Service supports handling failures.

If a message was not successfully handled, it does not get to the part where I delete the message from the queue. If it's a one-time failure, it is handled graciously. However, if it is an erroneous message, it makes its way into DLQ.

My question is what should be happening with DLQs later on? There are thousands of those messages stuck in the DLQ. How are they supposed to be handled?

I would love to hear some real-life examples and engineering processes that are in place in some of the organizations.

答:
The messages moved to DLQ are considered as you said, erroneous.

If the messages are erroneous due to a bug in the code etc, you should redrive these DLQ messages to source queue once you fixed the bug. So that they'll have another chance to be reprocessed.

It is very unlikely that "temporarly" erroneous messages are moved to DLQ, if you already configured the maxReceiveCount as 3 or more for your source queue. Temporary problems are mostly bypassed with this retry configuration.

And eventually DLQ is also an ordinary SQS queue which retains messages up to 14 days. Even if there are thousands of messages there, they will be gone. At this point, there are two options:

Messages in DLQ are "really" erroneous. So see the metrics, messages and logs to identify the root cause. If there is no bug to fix, it means you keep unrequired data in DLQ. So there is nothing wrong to lose them in 14 days. If there is a bug, fix it an simply redrive messages from DLQ to source queue.

You dont want to investigate through the messages to identify that what was the reason for failure, and you only want to persist message data for historical reasons (god knows why). You can create a lambda function to poll messages and persist in a desired target database.


问:
How to find a record by unique value inside an array in MongoDB?
I want to locate a record which has the "String to match" in his "affiliates.wallets" array. But for some reason, I'm unable to do it.

I was trying something like:

db.collection.findOne({ "affiliates.wallets": {$in: "[String to match]"}, (err, data) => console.log(err, data)})
```
<p>But it returns <code>null</code>. So, I'm asking for help.</p>
<p>Simplified Wallet Schema:</p>
<pre class="lang-js prettyprint-override"><code>Wallet {
  affiliates: {
    wallets: [String]
  }
}
</code>```

P.S: I'm using findOne method because this "String to match" which I'm using to locate the record is unique and it can be located only in one record.

答:
You don't need $in operator. You can do it like this:

db.collection.findOne({
  "affiliates.wallets": "String to match",
}, (err, data) => {
  console.log(err, data)
})
```

Body:
I want to locate a record which has the "String to match" in his "affiliates.wallets" array. But for some reason, I'm unable to do it.

I was trying something like:

db.collection.findOne({ "affiliates.wallets": {$in: "[String to match]"}, (err, data) => console.log(err, data)})

But it returns null. So, I'm asking for help.

Simplified Wallet Schema:

Wallet {
  affiliates: {
    wallets: [String]
  }
}

P.S: I'm using findOne method because this "String to match" which I'm using to locate the record is unique and it can be located only in one record.


问:
Python "not in" not correctly identifying strings which do not contain a particular letter
I am attempting to write a little program to play the popular game, Wordle.

One of my function attempts to remove words from a word bank which do not contain a particular letter. The function does a decent job, but I have discovered that the function occasionally fails to identify words that should be removed from the list. If I call on the function repeatedly, it will eventually eliminate all the correct words.

```<code>#Creates a list of 4266 five-letter words from a text file
five_letters = open("five.txt", "r")
five = five_letters.read()
five = five.split()

#Iterates across list and removes words that do not contain a particular letter
def eliminate_words_not_containing(list, letter):
    for word in list:
        if letter not in word:
            list.remove(word)
    return list

# Call on the function 10 times and print the length of the list after each call
print(len(five))
for i in range(10):
    five = eliminate_words_not_containing(five, "e")
    print(len(five))
</code>```

The output is:

```<code>4266
2932
2319
2070
2014
2010
2010
2010
2010
2010
2010
</code>```

How can I write the function so that it catches all the words that do not containing a particular letter the first time through?

Silly question: Is it possible for the program to be running too quickly, and it skips over words?

答:
You iterating over the original list, so when you remove one word the position isn't updated, try to make a copy of the list and iterate over it.

Edit: I'd try list comprehension if it was me so:

```<code>list = [word for word in list if letter not in word]
</code>```

Body:
I am attempting to write a little program to play the popular game, Wordle.

One of my function attempts to remove words from a word bank which do not contain a particular letter. The function does a decent job, but I have discovered that the function occasionally fails to identify words that should be removed from the list. If I call on the function repeatedly, it will eventually eliminate all the correct words.

#Creates a list of 4266 five-letter words from a text file
five_letters = open("five.txt", "r")
five = five_letters.read()
five = five.split()

#Iterates across list and removes words that do not contain a particular letter
def eliminate_words_not_containing(list, letter):
    for word in list:
        if letter not in word:
            list.remove(word)
    return list

# Call on the function 10 times and print the length of the list after each call
print(len(five))
for i in range(10):
    five = eliminate_words_not_containing(five, "e")
    print(len(five))

The output is:

4266
2932
2319
2070
2014
2010
2010
2010
2010
2010
2010

How can I write the function so that it catches all the words that do not containing a particular letter the first time through?

Silly question: Is it possible for the program to be running too quickly, and it skips over words?

Body:
You iterating over the original list, so when you remove one word the position isn't updated, try to make a copy of the list and iterate over it.

Edit: I'd try list comprehension if it was me so:

list = [word for word in list if letter not in word]


答:
Because you are modifying your list while you are iterating over it, you are skipping words.

If your list is ['word1', 'word2', 'word3'] and you call your eliminate function, you will be left with ['word2'] because you removed 'word1', then your for loop moved on to the 2nd index, which is now 'word3' from the original list (with 'word2' being the first word in the list after the removal of 'word1').

There are several ways to solve the problem, but one solution would be to remember the indices to remove:

def eliminate_words_not_containing(word_list, letter):
    to_remove = set()
    for i, word in enumerate(word_list):
        if letter not in word:
            to_remove.add(i)
    return [word for i, word in enumerate(word_list) if i not in to_remove]
```

Probably just a regular list comprehension would be better in this case, but the above would be generalized in case you want to do something more complicated with each entry.

(Also, it's not good practice to use the variable named list because it clobbers the built-in type list in python.)

Title: Python "not in" not correctly identifying strings which do not contain a particular letter

Body:
Because you are modifying your list while you are iterating over it, you are skipping words.

If your list is ['word1', 'word2', 'word3'] and you call your eliminate function, you will be left with ['word2'] because you removed 'word1', then your for loop moved on to the 2nd index, which is now 'word3' from the original list (with 'word2' being the first word in the list after the removal of 'word1').

There are several ways to solve the problem, but one solution would be to remember the indices to remove:

def eliminate_words_not_containing(word_list, letter):
    to_remove = set()
    for i, word in enumerate(word_list):
        if letter not in word:
            to_remove.add(i)
    return [word for i, word in enumerate(word_list) if i not in to_remove]

Probably just a regular list comprehension would be better in this case, but the above would be generalized in case you want to do something more complicated with each entry.

(Also, it's not good practice to use the variable named list because it clobbers the built-in type list in python.)


问:
Is there a correct way to pass arguments in slf4j?
Im using slf4j for tracing the information. My code is

```<code>private static final Logger log = LoggerFactory.getLogger(ObjectTest.class);

log.trace("Time taken to store " + count
            + " objects of size " + size +  " is " + (time) + " msecs");

log.trace("Time taken to store {} objects of size {} is {} msecs",
        new Object[] { count, size, time });

log.trace("Time taken to store {} objects of size {} is {} msecs",
        count, size, time);
</code>```

Which would be the preferred mechanism to log traces.

答:
3 is the best.

3 and 2 generate the same (or nearly the same) bytecode, but 3 is easier to type and is shorter, so 3 is better than 2.

If trace is not enabled, 1 must perform string concatenation ("Time taken to store " + count + ....) which is somewhat expensive, while 2 does the string concatenation only if trace is enabled, which is why 3 is better than 1.

ContentLicense: CC BY-SA 3.0

Body:
Im using slf4j for tracing the information. My code is

private static final Logger log = LoggerFactory.getLogger(ObjectTest.class);

log.trace("Time taken to store " + count
            + " objects of size " + size +  " is " + (time) + " msecs");

log.trace("Time taken to store {} objects of size {} is {} msecs",
        new Object[] { count, size, time });

log.trace("Time taken to store {} objects of size {} is {} msecs",
        count, size, time);

Which would be the preferred mechanism to log traces.


问:
Leaflet Control Search Error: Uncaught TypeError: L.Control.geocoder is not a function
I am new to Leaflet and I'm trying to add the Control Search in my map but I encounter this error

Uncaught TypeError: L.Control.geocoder is not a function

I already added these links

```<code><link rel="stylesheet" href="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.css" />
<script src="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.js"></script>
</code>```

I initialized my map

```<code>var map = L.map('map').setView([40.71455, -74.00712], 10);
</code>```

Then added basemap

```<code>var dark_matrix = L.tileLayer('https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png', {
minZoom: 3,
maxZoom: 20,
attribution: '© <a href="https://stadiamaps.com/">Stadia Maps</a>, © <a href="https://openmaptiles.org/">OpenMapTiles</a> © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors'
});
dark_matrix.addTo(map);
</code>```

Add the control like this

```<code>L.Control.geocoder().addTo(map);
</code>```

I also tried this one

```<code>var searchControl = L.Control.geocoder();
searchControl.addTo(map);
</code>```

But still does not work.

Here is the jsfiddle of the project https://jsfiddle.net/mgy01hwx/1/

答:
Just change the order of the script files. The plugin needs leaflet code to be imported first in order to work.

first import leaflet.js

then import leaflet-geocoder.js

```<code><script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
<script src="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.js"></script>
</code>```

Demo

Body:
I am new to Leaflet and I'm trying to add the Control Search in my map but I encounter this error

Uncaught TypeError: L.Control.geocoder is not a function

I already added these links

<link rel="stylesheet" href="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.css" />

I initialized my map

var map = L.map('map').setView([40.71455, -74.00712], 10);

Then added basemap

var dark_matrix = L.tileLayer('https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png', {
minZoom: 3,
maxZoom: 20,
attribution: '© Stadia Maps, © OpenMapTiles © OpenStreetMap contributors'
});
dark_matrix.addTo(map);

Add the control like this

L.Control.geocoder().addTo(map);

I also tried this one

var searchControl = L.Control.geocoder();
searchControl.addTo(map);

But still does not work.

Here is the jsfiddle of the project https://jsfiddle.net/mgy01hwx/1/

Body:
Just change the order of the script files. The plugin needs leaflet code to be imported first in order to work.

first import leaflet.js

then import leaflet-geocoder.js

<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
<script src="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.js"></script>

Demo


问:
keycloak Invalid parameter: redirect_uri
When I am trying to hit from my api to authenticate user from keycloak, but its giving me error Invalid parameter: redirect_uri on keycloak page. I have created my own realm apart from master. keycloak is running on http. Please help me.</p>

答:
We also saw this, but only on certain URLs. After seeing this clue, I realized that the Java URI constructor has to be able to decode it,
like so URI uri = URI.create(redirectUri);

We had a { and } in our URLs which normally worked fine, but when going through two layers of URL decode/encode, Java decided the { and } were invalid.

We'll be changing our curly braces to something else to get around the double encode/decode issue.


问:
How do I completely mock an imported service class
I am looking to test my next API route which uses the micro framework (similar enough to express when using next-connect).

I have a service:

```<code>export class UserService {
  constructor(...) {}

  async findUser({ email }: Pick<IUserModel, 'email'>) {
    ...
  }
}
</code>```

My API endpoint:

```<code>import { NextApiRequest, NextApiResponse } from 'next';
import nc from 'next-connect';
import { UserService } from './UserService'; // Mock and prevent execution

const userService = new UserService();

export default nc().post(async (req: NextApiRequest, res: NextApiResponse) => {
  try {
    userService.findUser({ email: 'john.doe@example.com' });
    return res.status(200).send({ done: true });
  } catch (error: any) {
    return res.status(500).end(error.message);
  }
});
</code>```

I would like to completely mock the import and prevent any dependent code from executing.

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

For example if there is a console.log() in the UserService constructor it should not be run because the import is a completely mocked import.

Update:

I've attempted to use jest.mock but they didn't seem to actually mock my imports. I've added a console.log in the UserService constructor and it continues to be triggered when using jest.mock.

```<code>import signup from './signup';

jest.mock('./UserService');

describe('signup', () => {
  it('should complete the happy path', async () => {
    const req: IncomingMessage = {} as unknown as IncomingMessage;
    const res: ServerResponse = {
      end: jest.fn(),
    } as unknown as ServerResponse;

    const actual = await signup(req, res);
    expect(actual).toBe(...);
  });
});
</code>```

答:
<s>jest.mock doesn't support mocking dependencies for imports outside of the actual test file (.spec.ts & .test.ts).</s> In my case I have a lot of dependencies in my Next API endpoint that cannot be mocked.

You'll have to find a pattern to inject the dependency into the endpoint and test it in isolation instead. I made use of the Nextjs middleware example here but there are likely other patterns that will work just as well.

```<code>// Helper method to wait for a middleware to execute before continuing
// And to throw an error when an error happens in a middleware
function runMiddleware(req: NextApiRequest, res: NextApiResponse, fn: Function) {
  return new Promise((resolve, reject) => {
    fn(req, res, (result: any) => {
      if (result instanceof Error) {
        return reject(result)
      }

      return resolve(result)
    })
  })
}

// Testable function for DI
export function post(
  _userService: UserService,
) {
  return async function(req: NextApiRequest, res: NextApiResponse) {
    ...
  }
}

// Endpoint
export default async function(req: NextApiRequest, res: NextApiResponse) {
  try {
    await runMiddleware(req, res, post(userService));

    return res.status(200).send({ done: true });
  } catch (error: any) {
    return res.status(500).end(error.message);
  }
};

// Test usage
describe('signup', () => {
  let userService: UserService;

  beforeAll(() => {
    userService = new UserService({} as unknown as UserRepository);
  });

  it('should complete the happy path', async () => {
    const findSpy = jest
      .spyOn(userService, 'find')
      .mockImplementation(async () => null);

    const req: NextApiRequest = {
      body: {
        email: 'user@test.com',
        password: '12345678',
      },
    } as unknown as NextApiRequest;

    const res: NextApiResponse = {} as unknown as NextApiResponse;

    await post(userService)(req, res);

    ...
  });
});

</code>```

Body:
I am looking to test my next API route which uses the micro framework (similar enough to express when using next-connect).

I have a service:

export class UserService {
  constructor(...) {}

  async findUser({ email }: Pick<IUserModel, 'email'>) {
    ...
  }
}

My API endpoint:

import { NextApiRequest, NextApiResponse } from 'next';
import nc from 'next-connect';
import { UserService } from './UserService'; // Mock and prevent execution

const userService = new UserService();

export default nc().post(async (req: NextApiRequest, res: NextApiResponse) => {
  try {
    userService.findUser({ email: 'john.doe@example.com' });
    return res.status(200).send({ done: true });
  } catch (error: any) {
    return res.status(500).end(error.message);
  }
});

I would like to completely mock the import and prevent any dependent code from executing.

import { UserService } from './UserService';

For example if there is a console.log() in the UserService constructor it should not be run because the import is a completely mocked import.

Update:

I've attempted to use jest.mock but they didn't seem to actually mock my imports. I've added a console.log in the UserService constructor and it continues to be triggered when using jest.mock.

import signup from './signup';

jest.mock('./UserService');

describe('signup', () => {
  it('should complete the happy path', async () => {
    const req: IncomingMessage = {} as unknown as IncomingMessage;
    const res: ServerResponse = {
      end: jest.fn(),
    } as unknown as ServerResponse;

    const actual = await signup(req, res);
    expect(actual).toBe(...);
  });
});

Body:
<s>jest.mock doesn't support mocking dependencies for imports outside of the actual test file (.spec.ts & .test.ts).</s> In my case I have a lot of dependencies in my Next API endpoint that cannot be mocked.

You'll have to find a pattern to inject the dependency into the endpoint and test it in isolation instead. I made use of the Nextjs middleware example here but there are likely other patterns that will work just as well.

// Helper method to wait for a middleware to execute before continuing
// And to throw an error when an error happens in a middleware
function runMiddleware(req: NextApiRequest, res: NextApiResponse, fn: Function) {
  return new Promise((resolve, reject) => {
    fn(req, res, (result: any) => {
      if (result instanceof Error) {
        return reject(result)
      }

      return resolve(result)
    })
  })
}

// Testable function for DI
export function post(
  _userService: UserService,
) {
  return async function(req: NextApiRequest, res: NextApiResponse) {
    ...
  }
}

// Endpoint
export default async function(req: NextApiRequest, res: NextApiResponse) {
  try {
    await runMiddleware(req, res, post(userService));

    return res.status(200).send({ done: true });
  } catch (error: any) {
    return res.status(500).end(error.message);
  }
};

// Test usage
describe('signup', () => {
  let userService: UserService;

  beforeAll(() => {
    userService = new UserService({} as unknown as UserRepository);
  });

  it('should complete the happy path', async () => {
    const findSpy = jest
      .spyOn(userService, 'find')
      .mockImplementation(async () => null);

    const req: NextApiRequest = {
      body: {
        email: 'user@test.com',
        password: '12345678',
      },
    } as unknown as NextApiRequest;

    const res: NextApiResponse = {} as unknown as NextApiResponse;

    await post(userService)(req, res);

    ...
  });
});


问:
How do I edit selected tab control tab items?
I'm making roblox exploit in Visual Studio 2019 wpf and I have tab system which is adding and removing tabs and I add text editor when tab is added which is on my case AvalonEdit, but how do I detect selected tab and then edit the text editor for like clear button, save file button, open file button, inject dll button etc.

For example I would do the clear button like this(if I didn't have tab system):

```<code>AvalonEditor.Text = "";
</code>```

But now I have the tab system idk how to do it so can anyone help me

答:
if (TextEditor != null) { TextEditor.Clear(); }

This should detect what tab the user is curentlly on and run a action on the avalon instance

Body:
I'm making roblox exploit in Visual Studio 2019 wpf and I have tab system which is adding and removing tabs and I add text editor when tab is added which is on my case AvalonEdit, but how do I detect selected tab and then edit the text editor for like clear button, save file button, open file button, inject dll button etc.

For example I would do the clear button like this(if I didn't have tab system):

AvalonEditor.Text = "";

But now I have the tab system idk how to do it so can anyone help me


问:
How to bind TextField and ProgressBar in JavaFx
I'm trying to Use reactive bindings to bind the value of alcoholPercentageField to the progress property of alcoholBar.
The progress bar will "full" when alcoholic content is set to 20 % and empty when the alcoholic content is 0

My Code-

```<code>    public void start(Stage stage) throws Exception {
    stage.setTitle("Mead calculator");

    // Creating the fields and components
    TextField waterAmountField = new TextField();

    TextField alcoholPercentageField = new TextField();

    TextField sugarAmountField = new TextField();
    Label meadTotalAmount = new Label();
    Label assessmentLabel = new Label("");
    //assessmentLabel.textProperty().bind(alcoholPercentageField.textProperty());

    //Conditional Binding Error

    assessmentLabel.textProperty().bind(Bindings.when((alcoholPercentageField.textProperty().lessThan(5))).then("Smart").otherwise("Bad"));

    ProgressBar alcoholBar = new ProgressBar();

    //Error is here
    alcoholBar.progressProperty().bind(alcoholPercentageField.textProperty() * 5);
</code>```

Rest of the Code: some visual things

```<code>GridPane grid = new GridPane();
    grid.setAlignment(Pos.CENTER);
    grid.setHgap(10);
    grid.setVgap(10);
    grid.setPadding(new Insets(25, 25, 25, 25));
    var columnOneConstraints = new ColumnConstraints(150, 150, Double.MAX_VALUE);
    columnOneConstraints.setHalignment(HPos.RIGHT);
    var columnTwoConstrains = new ColumnConstraints(200,200, Double.MAX_VALUE);
    columnTwoConstrains.setHgrow(Priority.SOMETIMES);
    grid.getColumnConstraints().addAll(columnOneConstraints, columnTwoConstrains);
    alcoholBar.setMaxWidth(Double.MAX_VALUE);
    GridPane.setColumnSpan(alcoholBar, 2);
    GridPane.setHalignment(assessmentLabel, HPos.RIGHT);
    sugarAmountField.setDisable(true);

    grid.add(new Label("Water (l):"), 0, 0);
    grid.add(waterAmountField, 1, 0);

    grid.add(new Label("Vol-%:"), 0, 1);
    grid.add(alcoholPercentageField, 1, 1);

    grid.add(new Label("Sugar (kg):"),  0, 2);
    grid.add(sugarAmountField, 1, 2);

    grid.add(new Label("Lemons: "), 0, 3);
    grid.add(new Label("To taste"), 1, 3);

    grid.add(new Label("Mead total (kg):"), 0, 4);
    grid.add(meadTotalAmount, 1, 4);

    grid.add(alcoholBar, 0, 5);
    grid.add(assessmentLabel, 1, 6);
    // Okay, layout creation stops here

    // And of course set the scene and show the stage as always
    stage.setScene(new Scene(grid, 500, 400));
    stage.show();
}
</code>```

}

答:
Use the Bindings API.

Note that the progress is supposed to be between 0 and 1, so if you are entering percentages, instead of proportions, into your text field you need to divide by 100:

```<code>alcoholBar.progressProperty().bind(Bindings.createDoubleBinding(
    () -> 0.05 * Double.parseDouble(alcoholPercentageField.getText()),
    alcoholPercentageField.textProperty()
));
</code>```

You might want to implement more complex logic to, e.g. check for a valid number, or at least non-empty text field.

Body:
I'm trying to Use reactive bindings to bind the value of alcoholPercentageField to the progress property of alcoholBar.
The progress bar will "full" when alcoholic content is set to 20 % and empty when the alcoholic content is 0

My Code-

    public void start(Stage stage) throws Exception {
    stage.setTitle("Mead calculator");

    // Creating the fields and components
    TextField waterAmountField = new TextField();

    TextField alcoholPercentageField = new TextField();

    TextField sugarAmountField = new TextField();
    Label meadTotalAmount = new Label();
    Label assessmentLabel = new Label("");
    //assessmentLabel.textProperty().bind(alcoholPercentageField.textProperty());

    //Conditional Binding Error

    assessmentLabel.textProperty().bind(Bindings.when((alcoholPercentageField.textProperty().lessThan(5))).then("Smart").otherwise("Bad"));

    ProgressBar alcoholBar = new ProgressBar();

    //Error is here
    alcoholBar.progressProperty().bind(alcoholPercentageField.textProperty() * 5);

Rest of the Code: some visual things

GridPane grid = new GridPane();
    grid.setAlignment(Pos.CENTER);
    grid.setHgap(10);
    grid.setVgap(10);
    grid.setPadding(new Insets(25, 25, 25, 25));
    var columnOneConstraints = new ColumnConstraints(150, 150, Double.MAX_VALUE);
    columnOneConstraints.setHalignment(HPos.RIGHT);
    var columnTwoConstrains = new ColumnConstraints(200,200, Double.MAX_VALUE);
    columnTwoConstrains.setHgrow(Priority.SOMETIMES);
    grid.getColumnConstraints().addAll(columnOneConstraints, columnTwoConstrains);
    alcoholBar.setMaxWidth(Double.MAX_VALUE);
    GridPane.setColumnSpan(alcoholBar, 2);
    GridPane.setHalignment(assessmentLabel, HPos.RIGHT);
    sugarAmountField.setDisable(true);

    grid.add(new Label("Water (l):"), 0, 0);
    grid.add(waterAmountField, 1, 0);

    grid.add(new Label("Vol-%:"), 0, 1);
    grid.add(alcoholPercentageField, 1, 1);

    grid.add(new Label("Sugar (kg):"),  0, 2);
    grid.add(sugarAmountField, 1, 2);

    grid.add(new Label("Lemons: "), 0, 3);
    grid.add(new Label("To taste"), 1, 3);

    grid.add(new Label("Mead total (kg):"), 0, 4);
    grid.add(meadTotalAmount, 1, 4);

    grid.add(alcoholBar, 0, 5);
    grid.add(assessmentLabel, 1, 6);
    // Okay, layout creation stops here

    // And of course set the scene and show the stage as always
    stage.setScene(new Scene(grid, 500, 400));
    stage.show();
}

}

Body:
Use the Bindings API.

Note that the progress is supposed to be between 0 and 1, so if you are entering percentages, instead of proportions, into your text field you need to divide by 100:

alcoholBar.progressProperty().bind(Bindings.createDoubleBinding(
    () -> 0.05 * Double.parseDouble(alcoholPercentageField.getText()),
    alcoholPercentageField.textProperty()
));

You might want to implement more complex logic to, e.g. check for a valid number, or at least non-empty text field.


问:
jquery ui draggable element appears behind other elements?
I am using jquery ui draggable, and eventually droppable to make it possible to reorder pictures into different boxes.

When I drag a picture out of the box it appears under all the other elements once it leaves its direct container.

While googling I was able to found to add:

```<code>   helper: 'clone',
   appendTo: "body"
</code>```

This makes it so what is being dragged appears on top of all elements, but it leaves the original copy still in the box and I do not want that.

Is there a way I can make the element stay on top of everything when being dragged? I have tried a high z-index to no avail.

Here is a jsfiddle that shows the first draggle element behind behind the second. it is not an issue the other way around.
i am not able to change the position relative on the containing divs without breaking a lot of other things.

http://jsfiddle.net/cBWhX/6/

答:
Stack wasn't working for me either. I was able to correct the z-index issue by using the appendTo property.

```<code>function setupDraggableFields($elements) {
    $elements.draggable({
        helper: "clone",
        handle: ".field-sort-handle",
        appendTo: ".section-container"
    });
}
</code>```

Body:
I am using jquery ui draggable, and eventually droppable to make it possible to reorder pictures into different boxes.

When I drag a picture out of the box it appears under all the other elements once it leaves its direct container.

While googling I was able to found to add:

   helper: 'clone',
   appendTo: "body"

This makes it so what is being dragged appears on top of all elements, but it leaves the original copy still in the box and I do not want that.

Is there a way I can make the element stay on top of everything when being dragged? I have tried a high z-index to no avail.

Here is a jsfiddle that shows the first draggle element behind behind the second. it is not an issue the other way around.
i am not able to change the position relative on the containing divs without breaking a lot of other things.

http://jsfiddle.net/cBWhX/6/

Body:
Stack wasn't working for me either. I was able to correct the z-index issue by using the appendTo property.

function setupDraggableFields($elements) {
    $elements.draggable({
        helper: "clone",
        handle: ".field-sort-handle",
        appendTo: ".section-container"
    });
}


问:
I am not able to add custom CSS to the scroll bar that i have created in a Card component in MUI react
```<code>import React from "react";
import Card from "@mui/material/Card";
import CardActions from "@mui/material/CardActions";
import CardContent from "@mui/material/CardContent";
import CardMedia from "@mui/material/CardMedia";
import Button from "@mui/material/Button";
import Typography from "@mui/material/Typography";
import Grid from "@mui/material/Grid";
import ShareIcon from "@mui/icons-material/Share";
import LocalLibraryIcon from "@mui/icons-material/LocalLibrary";
import { makeStyles } from '@mui/styles';

const useStyles = makeStyles({
  scrollBar: {
    "::-webkit-scrollbar": {
      width: "3px",
    },

    "::-webkit-scrollbar-track": {
      boxShadow: "inset 0 0 5px rgb(255, 251, 251)",
      borderRadius: "10px",
    },

    "::-webkit-scrollbar-thumb": {
      background: "#077DFA",
      borderRadius: "10px",
    },

    "::-webkit-scrollbar-thumb:hover": {
      background: "rgb(255, 251, 251)",
    }
  }
});

export default function MediaCard(props) {
  const classes = useStyles()

  return (

        <Grid item md={4} >

          <Card className={classes.scrollBar} sx={{ maxWidth: 345 , maxHeight : 345, overflowY: "scroll"}}>
            <CardMedia
              component="img"
              height="190"
              image={props.img}
              alt={props.alt}

            />

            <CardContent>
              <Typography gutterBottom variant="h5" component="div">
                {props.headline}
              </Typography>
              <Typography variant="body2" color="text.secondary">
                {props.content}
              </Typography>
            </CardContent>
            <CardActions>
              <Button
                size="small"
                href=""
                variant="contained"
                endIcon={<ShareIcon />}
              >
                {" "}
                Share
              </Button>
              <Button
                sx={{ marginLeft: ".5rem" }}
                target="_blank"
                size="small"
                variant="contained"
                href={props.learnMore}
                endIcon={<LocalLibraryIcon />}
              >
                Learn More
              </Button>
            </CardActions>
          </Card>
        </Grid>
  );
}
</code>```

When I create a custom styles for the scroll bar by importing makeStyles function and store that under the useStyles hook and when I fire that hook and store it under classes, and finally use that classes inside class name of Card component, I see scrollbar styles unchanged. What could be the cause of this problem?

答:
You can customise default scroll bar with these css codes

::-webkit-scrollbar {
  width: 8px;
}

::-webkit-scrollbar-track {
  -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
  -webkit-border-radius: 5px;
  border-radius: 5px;
}

::-webkit-scrollbar-thumb {
  -webkit-border-radius: 5px;
  border-radius: 5px;
  background: #BB2020;
  -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.5);
}

::-webkit-scrollbar-thumb:window-inactive {
  background: #BB2020;
}

.scroll-box {
  overflow-y: scroll;
  height: 200px;
  border: 1px solid #ccc;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div class="scroll-box">
      <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas vero,
        tempore earum blanditiis corporis nesciunt pariatur, et illo quidem
        ipsum minus perferendis! Deleniti sapiente, doloremque eaque sit id
        similique nulla. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas vero,
        tempore earum blanditiis corporis nesciunt pariatur, et illo quidem
        ipsum minus perferendis! Deleniti sapiente, doloremque eaque sit id
        similique nulla.

        Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas vero,
        tempore earum blanditiis corporis nesciunt pariatur, et illo quidem
        ipsum minus perferendis! Deleniti sapiente, doloremque eaque sit id
        similique nulla. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas vero,
        tempore earum blanditiis corporis nesciunt pariatur, et illo quidem
        ipsum minus perferendis! Deleniti sapiente, doloremque eaque sit id
        similique nulla.

      </p>
    </div>
  </body>
</html></code>```

Body:
import React from "react";
import Card from "@mui/material/Card";
import CardActions from "@mui/material/CardActions";
import CardContent from "@mui/material/CardContent";
import CardMedia from "@mui/material/CardMedia";
import Button from "@mui/material/Button";
import Typography from "@mui/material/Typography";
import Grid from "@mui/material/Grid";
import ShareIcon from "@mui/icons-material/Share";
import LocalLibraryIcon from "@mui/icons-material/LocalLibrary";
import { makeStyles } from '@mui/styles';

const useStyles = makeStyles({
  scrollBar: {
    "::-webkit-scrollbar": {
      width: "3px",
    },

    "::-webkit-scrollbar-track": {
      boxShadow: "inset 0 0 5px rgb(255, 251, 251)",
      borderRadius: "10px",
    },

    "::-webkit-scrollbar-thumb": {
      background: "#077DFA",
      borderRadius: "10px",
    },

    "::-webkit-scrollbar-thumb:hover": {
      background: "rgb(255, 251, 251)",
    }
  }
});

export default function MediaCard(props) {
  const classes = useStyles()

  return (

        <Grid item md={4} >

          <Card className={classes.scrollBar} sx={{ maxWidth: 345 , maxHeight : 345, overflowY: "scroll"}}>
            <CardMedia
              component="img"
              height="190"
              image={props.img}
              alt={props.alt}

            />

            <CardContent>
              <Typography gutterBottom variant="h5" component="div">
                {props.headline}
              </Typography>
              <Typography variant="body2" color="text.secondary">
                {props.content}
              </Typography>
            </CardContent>
            <CardActions>
              <Button
                size="small"
                href=""
                variant="contained"
                endIcon={<ShareIcon />}
              >
                {" "}
                Share
              </Button>
              <Button
                sx={{ marginLeft: ".5rem" }}
                target="_blank"
                size="small"
                variant="contained"
                href={props.learnMore}
                endIcon={<LocalLibraryIcon />}
              >
                Learn More
              </Button>
            </CardActions>
          </Card>
        </Grid>
  );
}

When I create a custom styles for the scroll bar by importing makeStyles function and store that under the useStyles hook and when I fire that hook and store it under classes, and finally use that classes inside class name of Card component, I see scrollbar styles unchanged. What could be the cause of this problem?

Body:
You can customise default scroll bar with these css codes

::-webkit-scrollbar {
  width: 8px;
}

::-webkit-scrollbar-track {
  -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
  -webkit-border-radius: 5px;
  border-radius: 5px;
}

::-webkit-scrollbar-thumb {
  -webkit-border-radius: 5px;
  border-radius: 5px;
  background: #BB2020;
  -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.5);
}

::-webkit-scrollbar-thumb:window-inactive {
  background: #BB2020;
}

.scroll-box {
  overflow-y: scroll;
  height: 200px;
  border: 1px solid #ccc;
}

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div class="scroll-box">
      <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas vero,
        tempore earum blanditiis corporis nesciunt pariatur, et illo quidem
        ipsum minus perferendis! Deleniti sapiente, doloremque eaque sit id
        similique nulla. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas vero,
        tempore earum blanditiis corporis nesciunt pariatur, et illo quidem
        ipsum minus perferendis! Deleniti sapiente, doloremque eaque sit id
        similique nulla.

        Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas vero,
        tempore earum blanditiis corporis nesciunt pariatur, et illo quidem
        ipsum minus perferendis! Deleniti sapiente, doloremque eaque sit id
        similique nulla. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas vero,
        tempore earum blanditiis corporis nesciunt pariatur, et illo quidem
        ipsum minus perferendis! Deleniti sapiente, doloremque eaque sit id
        similique nulla.

      </p>
    </div>
  </body>
</html>


问:
Why does click event handler fire immediately upon page load?
I playing around with a function that I want to bind to all the links. At the present the function fires when the page loads, instead of when I click on the link.

Here's my code. (I can post the function showDiv(), if you need to see it.) Can you tell if I'm doing something wrong or stupid here?

```<code>$(document).ready(function(){

    $('a.test').bind("click", showDiv());

});
</code>```

Thanks!

答: Change it to: $('a.test').bind("click", showDiv); (do not put parens around showDiv since you want to pass the function reference).

Body:
I playing around with a function that I want to bind to all the links. At the present the function fires when the page loads, instead of when I click on the link.

Here's my code. (I can post the function showDiv(), if you need to see it.) Can you tell if I'm doing something wrong or stupid here?

$(document).ready(function(){

    $('a.test').bind("click", showDiv());

});

Thanks!


问:
How to get a list of all the Python standard library modules?
I want something like sys.builtin_module_names except for the standard library. Other things that didn't work:

sys.modules - only shows modules that have already been loaded

sys.prefix - a path that would include non-standard library modules and doesn't seem to work inside a virtualenv.

The reason I want this list is so that I can pass it to the --ignore-module or --ignore-dir command line options of trace.

So ultimately, I want to know how to ignore all the standard library modules when using trace or sys.settrace.

答:
This isn't perfect, but should get you pretty close if you can't run 3.10:

import os
import distutils.sysconfig

def get_stdlib_module_names():
    stdlib_dir = distutils.sysconfig.get_python_lib(standard_lib=True)
    return {f.replace(".py", "") for f in os.listdir(stdlib_dir)}
```

This misses some modules such as sys, math, time, and itertools.

My use case is logging which modules were imported during an app run, so having a rough filter for stdlib modules is fine. Also I return it as a set rather than a list so membership checks are faster.

Body:
This isn't perfect, but should get you pretty close if you can't run 3.10:

import os
import distutils.sysconfig

def get_stdlib_module_names():
    stdlib_dir = distutils.sysconfig.get_python_lib(standard_lib=True)
    return {f.replace(".py", "") for f in os.listdir(stdlib_dir)}

This misses some modules such as sys, math, time, and itertools.

My use case is logging which modules were imported during an app run, so having a rough filter for stdlib modules is fine. Also I return it as a set rather than a list so membership checks are faster.


问:
Algolia autocomplete search box doesn't show up in laravel
I followed the documantation:

npm install @algolia/autocomplete-js

npm install @algolia/autocomplete-theme-classic

shop.blade.php:

```<code>...
<div id="autocomplete"></div>
<script type="module">
    import { autocomplete } from './@algolia/autocomplete-js';
    import './@algolia/autocomplete-theme-classic';

    autocomplete({
        container: '#autocomplete',
        placeholder: 'Search for products',
        getSources() {
            return [];
        },
    });
</script>
</code>```

When I open the page, there's not any box for searching, only

 that's empty.

Please tell me what is wrong Thanks

Body:
I followed the documantation:

npm install @algolia/autocomplete-js

npm install @algolia/autocomplete-theme-classic

shop.blade.php:

...

When I open the page, there's not any box for searching, only

 that's empty.

Please tell me what is wrong Thanks

Body:
Are you getting any errors in your browser developer console -- for instance, can you confirm  the library loading?

I was able to build up an autocomplete box using this blog, but I'm using vanilla Javascript, not <script> modules. I can confirm, that if the code executes, you should at least see a search button/box with that code, even though there aren't any sources wired to the search box.

https://www.algolia.com/blog/ux/replicating-the-algolia-documentation-search-with-autocomplete/


问:
How to create a Typescript type based on the keys/values of a dictionary?
Is there a way to automatically generate a type based on a dictionary value? E.g. given this dictionary of constant values:

```<code>export const SHIPMETHODS: OptionsMap<UpsShipMethodOption> = {
    'UPS': 'GND',
    'UPS AIR2': '2DA',
    'UPS 3DAY SELECT': '3DS'
}
</code>```

Is there a way to automatically generate a type like this, without having to duplicate everything?

```<code>export type ShipMethodOptionMap = {
    'UPS': 'GND',
    'UPS AIR2': '2DA',
    'UPS 3DAY SELECT': '3DS'
}
</code>```

Unfortunately keyof doesn't seem to work since it's an object and not a type, so this doesn't work:

```<code>export type UpsShipMethodOption = keyof SHIPMETHODS // Doesn't work
</code>```

I also tried using mapped types with a predeclared union type of the keys, but it doesn't work either:

```<code>/*
  Type 'KeyOptions' is not assignable to type 'string | number | symbol'.
  Type 'KeyOptions' is not assignable to type 'symbol'.ts(2322)
*/
export type OptionsMap<KeyOptions> = {
    readonly [Property in KeyOptions]: string;
}

export const SHIPMETHODS: OptionsMap<UpsShipMethodOption> = {
    'UPS': 'GND',
    'UPS AIR2': '2DA',
    'UPS 3DAY SELECT': '3DS'
}
export type UpsShipMethodOption = 'UPS' | 'UPS AIR2' | 'UPS 3DAY SELECT'
</code>```

I have a bunch of such dictionaries, and most of them are quite large (30+ keys). Duplicating the dictionary into a type everywhere would make it a pain to maintain in case the values change, so any help with this would be great!

答:
I think you just want the typeof operator. It simply gets the type of a value.

```<code>const SHIPMETHODS = {
    'UPS': 'GND',
    'UPS AIR2': '2DA',
    'UPS 3DAY SELECT': '3DS'
} as const // as const is important.

type ShipMethodOptionMap = typeof SHIPMETHODS
/*
type ShipMethodOptionMap = {
    readonly UPS: "GND";
    readonly 'UPS AIR2': "2DA";
    readonly 'UPS 3DAY SELECT': "3DS";
}
*/

type UpsShipMethodOption = keyof ShipMethodOptionMap
// type UpsShipMethodOption = "UPS" | "UPS AIR2" | "UPS 3DAY SELECT"
</code>```

Just note the as const on your object which allows typescript to infer the string literals so they can become part of the type.

Playground

Body:
Is there a way to automatically generate a type based on a dictionary value? E.g. given this dictionary of constant values:

export const SHIPMETHODS: OptionsMap<UpsShipMethodOption> = {
    'UPS': 'GND',
    'UPS AIR2': '2DA',
    'UPS 3DAY SELECT': '3DS'
}

Is there a way to automatically generate a type like this, without having to duplicate everything?

export type ShipMethodOptionMap = {
    'UPS': 'GND',
    'UPS AIR2': '2DA',
    'UPS 3DAY SELECT': '3DS'
}

Unfortunately keyof doesn't seem to work since it's an object and not a type, so this doesn't work:

export type UpsShipMethodOption = keyof SHIPMETHODS // Doesn't work

I also tried using mapped types with a predeclared union type of the keys, but it doesn't work either:

/*
  Type 'KeyOptions' is not assignable to type 'string | number | symbol'.
  Type 'KeyOptions' is not assignable to type 'symbol'.ts(2322)
*/
export type OptionsMap<KeyOptions> = {
    readonly [Property in KeyOptions]: string;
}

export const SHIPMETHODS: OptionsMap<UpsShipMethodOption> = {
    'UPS': 'GND',
    'UPS AIR2': '2DA',
    'UPS 3DAY SELECT': '3DS'
}
export type UpsShipMethodOption = 'UPS' | 'UPS AIR2' | 'UPS 3DAY SELECT'

I have a bunch of such dictionaries, and most of them are quite large (30+ keys). Duplicating the dictionary into a type everywhere would make it a pain to maintain in case the values change, so any help with this would be great!

Body:
I think you just want the typeof operator. It simply gets the type of a value.

const SHIPMETHODS = {
    'UPS': 'GND',
    'UPS AIR2': '2DA',
    'UPS 3DAY SELECT': '3DS'
} as const // as const is important.

type ShipMethodOptionMap = typeof SHIPMETHODS
/*
type ShipMethodOptionMap = {
    readonly UPS: "GND";
    readonly 'UPS AIR2': "2DA";
    readonly 'UPS 3DAY SELECT': "3DS";
}
*/

type UpsShipMethodOption = keyof ShipMethodOptionMap
// type UpsShipMethodOption = "UPS" | "UPS AIR2" | "UPS 3DAY SELECT"

Just note the as const on your object which allows typescript to infer the string literals so they can become part of the type.

Playground


问:
only when use iphone simulator
I have this error:

The following FileSystemException was thrown resolving an image codec:
Cannot open file, path = '/Users/todo/Library/Developer/CoreSimulator/Devices/82205CEC-3D83-4A29-BF17-01C5B0515F71/data/Containers/Data/Application/035B9913-BEC5-46BA-84A5-8C1FE3C4E671/tmp/image_picker_B8D488A3-2790-4D53-A5D8-52E57E2C4108-76094-000003172DF085D2.jpg' (OS Error: No such file or directory, errno = 2)

When the exception was thrown, this was the stack

only when use  iphone simulator while android emulator no problem

```import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../app/utility.dart';
import '../db/aql_db.dart';
import '../globals.dart';
import '../menu_page.dart';
import '../model/aql_model.dart';
import '../widget/input_text.dart';
import 'dart:io';
import 'package:http/http.dart' as http;

var _current = resultsFld[0];

class AqlPg extends StatefulWidget {
  const AqlPg({Key? key}) : super(key: key);

  @override
  State<AqlPg> createState() => _AqlPgState();
}

class _AqlPgState extends State<AqlPg> {
  final List<TextEditingController> _criticalController = [];
  final List<TextEditingController> _majorController = [];
  final List<TextEditingController> _minorController = [];
  final List<TextEditingController> _imgCommintControllers = [];
  final _irController = TextEditingController();

  bool clickedCentreFAB =
      false; //boolean used to handle container animation which expands from the FAB
  int selectedIndex =
      0; //to handle which item is currently selected in the bottom app bar

  //call this method on click of each bottom app bar item to update the screen
  void updateTabSelection(int index, String buttonText) {
    setState(() {
      selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    //
    _irController.text = aqltbl.ir ?? '';
    String _current = aqltbl.result ?? resultsFld[0];
    //
    return Scaffold(
      body: SingleChildScrollView(
        scrollDirection: Axis.vertical,
        child: Column(
          children: [
            //---- stack for FloatingActionButton
            Stack(
              children: <Widget>[
                //this is the code for the widget container that comes from behind the floating action button (FAB)
                Align(
                  alignment: FractionalOffset.bottomCenter,
                  child: AnimatedContainer(
                    child: const Text(
                      'Hello',
                      style: TextStyle(fontSize: 18, color: whiteColor),
                    ),
                    duration: const Duration(milliseconds: 250),
                    //if clickedCentreFAB == true, the first parameter is used. If it's false, the second.
                    height: clickedCentreFAB
                        ? MediaQuery.of(context).size.height
                        : 10.0,
                    width: clickedCentreFAB
                        ? MediaQuery.of(context).size.height
                        : 10.0,
                    decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(
                            clickedCentreFAB ? 0.0 : 300.0),
                        color: Colors.blue),
                  ),
                ),
              ],
            ),

            // --- Top Page Title
            const SizedBox(
              height: 50,
            ),
            const Center(
              child: Text(
                'Aql page',
                style: TextStyle(
                    fontSize: 30,
                    fontWeight: FontWeight.bold,
                    color: medBlueColor),
              ),
            ),
            Text(
              'Shipment no:$shipmentId',
              style: const TextStyle(color: medBlueColor),
            ),

            //--- input container
            SingleChildScrollView(
              scrollDirection: Axis.horizontal,
              child: Row(
                children: [
                  Container(
                    height: 270,
                    width: 300,
                    margin: const EdgeInsets.only(top: 5),
                    child: ListView.builder(
                        itemCount: (aqltbl.aql ?? []).length,
                        scrollDirection: Axis.horizontal,
                        itemBuilder: (context, index) {
                          //here
                          var _aqlList = aqltbl.aql![index];
                          //
                          if (aqltbl.aql!.length > _criticalController.length) {
                            _criticalController.add(TextEditingController());
                            _majorController.add(TextEditingController());
                            _minorController.add(TextEditingController());
                          }
                          //
                          _criticalController[index].text =
                              _aqlList.critical ?? '';
                          _majorController[index].text = _aqlList.major ?? '';
                          _minorController[index].text = _aqlList.minor ?? '';
                          //
                          return Column(
                            children: [
                              Container(
                                height: 260,
                                width: 200,
                                margin: const EdgeInsets.only(left: 10),
                                padding: const EdgeInsets.all(10),
                                // ignore: prefer_const_constructors
                                decoration: BoxDecoration(
                                  color: lightBlue,
                                  borderRadius: BorderRadius.circular(10),
                                ),
                                child: Column(
                                  children: [
                                    Text(
                                      (_aqlList.name ?? '').toString(),
                                      style: const TextStyle(
                                        color: medBlueColor,
                                        fontSize: 13,
                                      ),
                                    ),
                                    // ignore: prefer_const_constructors
                                    MyInputField(
                                      title: 'critical',
                                      hint: 'write critical ',
                                      borderColor: borderColor,
                                      textColor: textColor,
                                      hintColor: hintColor,
                                      controller: _criticalController[index],
                                      onSubmit: (value) {
                                        setState(() {
                                          aqltbl.aql![index].critical = value;
                                          _save();
                                        });
                                      },
                                    ),
                                    MyInputField(
                                      title: 'majority',
                                      hint: 'write majority ',
                                      borderColor: borderColor,
                                      textColor: textColor,
                                      hintColor: hintColor,
                                      controller: _majorController[index],
                                      onSubmit: (value) {
                                        setState(() {
                                          aqltbl.aql![index].major = value;
                                          _save();
                                        });
                                      },
                                    ),
                                    MyInputField(
                                      title: 'minority',
                                      hint: 'write minority ',
                                      borderColor: borderColor,
                                      textColor: textColor,
                                      hintColor: hintColor,
                                      controller: _minorController[index],
                                      onSubmit: (value) {
                                        setState(() {
                                          aqltbl.aql![index].minor = value;
                                          _save();
                                        });
                                      },
                                    ),
                                  ],
                                ),
                              ),
                            ],
                          );
                        }),
                  ),
                  Container(
                    height: 270,
                    width: 300,
                    margin: const EdgeInsets.only(right: 10, left: 20),
                    padding: const EdgeInsets.only(
                        left: 10, bottom: 3, right: 10, top: 5),
                    decoration: const BoxDecoration(
                      color: lightBlue,
                    ),
                    child: Column(
                      children: [
                        const Text(
                          'Summery results',
                          style: TextStyle(color: medBlueColor),
                        ),
                        Container(
                          margin: const EdgeInsets.only(top: 10, bottom: 5),
                          alignment: Alignment.centerLeft,
                          child: const Text(
                            'Results',
                            style: TextStyle(color: medBlueColor),
                          ),
                        ),

                        Container(
                          padding: const EdgeInsets.only(right: 5, left: 5),
                          decoration: BoxDecoration(
                              color: whiteColor,
                              borderRadius: BorderRadius.circular(10),
                              border: Border.all(
                                color: borderColor,
                              )),
                          child: DropdownButtonHideUnderline(
                            child: DropdownButton<String>(
                              focusColor: whiteColor,
                              value: aqltbl.result,
                              hint: const Text('select result'),
                              isExpanded: true,
                              iconSize: 36,
                              icon: const Icon(Icons.arrow_drop_down),
                              items: resultsFld.map((res) {
                                return DropdownMenuItem<String>(
                                  value: res,
                                  child: Text(
                                    res,
                                    style: const TextStyle(
                                        fontFamily: 'tajawal',
                                        fontSize: 15,
                                        color: medBlueColor),
                                  ),
                                );
                              }).toList(),
                              onChanged: (val) {
                                setState(() {
                                  aqltbl.result = val;
                                });
                                _save();
                              },
                            ),
                          ),
                        ),
                        // aqltbl.result = selRes;
                        MyInputField(
                          width: 300,
                          title: 'information remarks (ir)',
                          hint: '',
                          maxLines: 3,
                          borderColor: borderColor,
                          textColor: textColor,
                          hintColor: hintColor,
                          controller: _irController,
                          onSubmit: (value) {
                            aqltbl.ir = value;
                            _save();
                          },
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
            //Images Container
            Container(
              height: 400,
              padding: const EdgeInsets.all(0),
              margin: const EdgeInsets.only(bottom: 10, left: 10),
              decoration: const BoxDecoration(color: lightGrey),
              child: (aqltbl.images ?? []).isEmpty
                  ? Column(
                      children: [
                        Image.asset(
                          'images/empty-photo.jpg',
                          height: 300,
                        ),
                        Container(
                            margin: const EdgeInsets.only(top: 10),
                            child: Row(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: const [
                                Text('Click'),
                                Text(
                                  'Camera button',
                                  style: TextStyle(fontWeight: FontWeight.bold),
                                ),
                                Text(' to add new photo'),
                              ],
                            )),
                      ],
                    )
                  : ListView.builder(
                      scrollDirection: Axis.horizontal,
                      itemCount: (aqltbl.images ?? []).length,
                      itemBuilder: (context, imgIndex) {
                        String? _image =
                            (aqltbl.images ?? [])[imgIndex].name.toString();
                        inspect('aql image file');
                        File(_image).exists() == true
                            ? inspect('image exist')
                            : inspect('not exist: ' + _image);
                        inspect('_image: ' + _image);
                        if (aqltbl.images!.length >
                            _imgCommintControllers.length) {
                          _imgCommintControllers.add(TextEditingController());
                        }
                        _imgCommintControllers[imgIndex].text =
                            aqltbl.images![imgIndex].imgComment!;

                        inspect(_imgCommintControllers.length);

                        return Container(
                            margin: const EdgeInsets.only(left: 5),
                            height: 300,
                            child: Column(
                              children: [
                                Stack(
                                  children: [
                                    Image.file(
                                      File(_image),
                                      height: 300,
                                    ),
                                    Container(
                                      decoration: const BoxDecoration(
                                        color: medBlueColor,
                                      ),
                                      child: IconButton(
                                          onPressed: () {
                                            inspect('clear');
                                            String imgName =
                                                aqltbl.images![imgIndex].name ??
                                                    '';
                                            aqltbl.images!.removeAt(imgIndex);
                                            // aqltbl.images!.removeWhere(
                                            //     (item) => item.name == imgName);
                                            _imgCommintControllers
                                                .removeAt(imgIndex);
                                            setState(() {});
                                          },
                                          color: whiteColor,
                                          icon: const Icon(Icons.clear)),
                                    )
                                  ],
                                ),
                                MyInputField(
                                  title: 'Write remarks about image',
                                  hint: '',
                                  controller: _imgCommintControllers[imgIndex],
                                  onSubmit: (value) {
                                    aqltbl.images![imgIndex].imgComment = value;
                                    aqltbl.images![imgIndex].name = _image;
                                    _save();
                                  },
                                ),
                              ],
                            ));
                      }),
            ),
          ],
        ),
      ),
      // --- FloatingActionButton
      floatingActionButtonLocation: FloatingActionButtonLocation
          .centerDocked, //specify the location of the FAB
      floatingActionButton: FloatingActionButton(
        backgroundColor: medBlueColor,
        onPressed: () {
          inspect(aqltbl);
          setState(() {
            clickedCentreFAB =
                !clickedCentreFAB; //to update the animated container
          });
        },
        tooltip: "Centre FAB",
        child: Container(
          margin: const EdgeInsets.all(15.0),
          child: const Icon(Icons.send),
        ),
        elevation: 4.0,
      ),

      // --- bottom action bar
      bottomNavigationBar: BottomAppBar(
        child: Container(
          margin: const EdgeInsets.only(left: 12.0, right: 12.0),
          child: Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              //to leave space in between the bottom app bar items and below the FAB
              IconButton(
                //update the bottom app bar view each time an item is clicked
                onPressed: () {
                  // updateTabSelection(0, "Home");
                  Get.to(const MainMenu());
                },
                iconSize: 27.0,
                icon: Image.asset(
                  'images/logo.png',
                  color: medBlueColor,
                ),
              ),

              const SizedBox(
                width: 50.0,
              ),
              IconButton(
                onPressed: () async {
                  // updateTabSelection(2, "Incoming");
                  await _takeImage('gallery');
                },
                iconSize: 27.0,
                icon: const Icon(
                  Icons.image_outlined,
                  color: medBlueColor,
                ),
              ),
              IconButton(
                onPressed: () async {
                  // updateTabSelection(1, "Outgoing");
                  await _takeImage('camera');
                },
                iconSize: 27.0,
                icon: const Icon(
                  Icons.camera_alt,
                  color: medBlueColor,
                ),
              ),
            ],
          ),
        ),
        //to add a space between the FAB and BottomAppBar
        shape: const CircularNotchedRectangle(),
        //color of the BottomAppBar
        color: Colors.white,
      ),
    );
  }

  _save() {
    inspect('submit');
    saveAql(shipmentId, aqltbl);
    box.write('aql'+shipmentId.toString(), aqltbl);
  }

  _takeImage(method) async {
    String _imgPath = await imageFromDevice(method);
    if (_imgPath != empty) {
      ImagesModel imgMdl = ImagesModel();
      imgMdl.name = _imgPath;
      imgMdl.imgComment = '';
      if (aqltbl.images != null) {
        // _saveLocaly(close: 0);
        setState(() {
          aqltbl.images!.add(imgMdl);
          _save();
        });
      }
    }
  }

  Future _sendAqlToServer() async {
    try {
      var response = await http.post(urlSendProductPhoto, body: {
        'aql': json.encode(aqltbl).toString(),
        'id': shipmentId.toString(),
      });
      if (response.statusCode == 200) {
        Get.snackbar('Success', 'Image successfully uploaded');
        return response.body;
      } else {
        Get.snackbar('Fail', 'Image not uploaded');
        inspect('Request failed with status: ${response.statusCode}.');
        return 'empty';
      }
    } catch (socketException) {
      Get.snackbar('warning', 'Image not uploaded');
      return 'empty';
    }
  }

}

```

答: Try following the path that it is saying it cannot find in your computer, I had a similar issue, I tried opening an Iphone 12 instead of an Iphone 13 and it worked out the issue, my problem was I inadvertently deleted a few files I shouldn't have.</p>

Title: only when use iphone simulator

Body:
I have this error:

The following FileSystemException was thrown resolving an image codec:
Cannot open file, path = '/Users/todo/Library/Developer/CoreSimulator/Devices/82205CEC-3D83-4A29-BF17-01C5B0515F71/data/Containers/Data/Application/035B9913-BEC5-46BA-84A5-8C1FE3C4E671/tmp/image_picker_B8D488A3-2790-4D53-A5D8-52E57E2C4108-76094-000003172DF085D2.jpg' (OS Error: No such file or directory, errno = 2)

When the exception was thrown, this was the stack

only when use  iphone simulator while android emulator no problem

import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../app/utility.dart';
import '../db/aql_db.dart';
import '../globals.dart';
import '../menu_page.dart';
import '../model/aql_model.dart';
import '../widget/input_text.dart';
import 'dart:io';
import 'package:http/http.dart' as http;

var _current = resultsFld[0];

class AqlPg extends StatefulWidget {
  const AqlPg({Key? key}) : super(key: key);

  @override
  State<AqlPg> createState() => _AqlPgState();
}

class _AqlPgState extends State<AqlPg> {
  final List<TextEditingController> _criticalController = [];
  final List<TextEditingController> _majorController = [];
  final List<TextEditingController> _minorController = [];
  final List<TextEditingController> _imgCommintControllers = [];
  final _irController = TextEditingController();

  bool clickedCentreFAB =
      false; //boolean used to handle container animation which expands from the FAB
  int selectedIndex =
      0; //to handle which item is currently selected in the bottom app bar

  //call this method on click of each bottom app bar item to update the screen
  void updateTabSelection(int index, String buttonText) {
    setState(() {
      selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    //
    _irController.text = aqltbl.ir ?? '';
    String _current = aqltbl.result ?? resultsFld[0];
    //
    return Scaffold(
      body: SingleChildScrollView(
        scrollDirection: Axis.vertical,
        child: Column(
          children: [
            //---- stack for FloatingActionButton
            Stack(
              children: <Widget>[
                //this is the code for the widget container that comes from behind the floating action button (FAB)
                Align(
                  alignment: FractionalOffset.bottomCenter,
                  child: AnimatedContainer(
                    child: const Text(
                      'Hello',
                      style: TextStyle(fontSize: 18, color: whiteColor),
                    ),
                    duration: const Duration(milliseconds: 250),
                    //if clickedCentreFAB == true, the first parameter is used. If it's false, the second.
                    height: clickedCentreFAB
                        ? MediaQuery.of(context).size.height
                        : 10.0,
                    width: clickedCentreFAB
                        ? MediaQuery.of(context).size.height
                        : 10.0,
                    decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(
                            clickedCentreFAB ? 0.0 : 300.0),
                        color: Colors.blue),
                  ),
                ),
              ],
            ),

            // --- Top Page Title
            const SizedBox(
              height: 50,
            ),
            const Center(
              child: Text(
                'Aql page',
                style: TextStyle(
                    fontSize: 30,
                    fontWeight: FontWeight.bold,
                    color: medBlueColor),
              ),
            ),
            Text(
              'Shipment no:$shipmentId',
              style: const TextStyle(color: medBlueColor),
            ),

            //--- input container
            SingleChildScrollView(
              scrollDirection: Axis.horizontal,
              child: Row(
                children: [
                  Container(
                    height: 270,
                    width: 300,
                    margin: const EdgeInsets.only(top: 5),
                    child: ListView.builder(
                        itemCount: (aqltbl.aql ?? []).length,
                        scrollDirection: Axis.horizontal,
                        itemBuilder: (context, index) {
                          //here
                          var _aqlList = aqltbl.aql![index];
                          //
                          if (aqltbl.aql!.length > _criticalController.length) {
                            _criticalController.add(TextEditingController());
                            _majorController.add(TextEditingController());
                            _minorController.add(TextEditingController());
                          }
                          //
                          _criticalController[index].text =
                              _aqlList.critical ?? '';
                          _majorController[index].text = _aqlList.major ?? '';
                          _minorController[index].text = _aqlList.minor ?? '';
                          //
                          return Column(
                            children: [
                              Container(
                                height: 260,
                                width: 200,
                                margin: const EdgeInsets.only(left: 10),
                                padding: const EdgeInsets.all(10),
                                // ignore: prefer_const_constructors
                                decoration: BoxDecoration(
                                  color: lightBlue,
                                  borderRadius: BorderRadius.circular(10),
                                ),
                                child: Column(
                                  children: [
                                    Text(
                                      (_aqlList.name ?? '').toString(),
                                      style: const TextStyle(
                                        color: medBlueColor,
                                        fontSize: 13,
                                      ),
                                    ),
                                    // ignore: prefer_const_constructors
                                    MyInputField(
                                      title: 'critical',
                                      hint: 'write critical ',
                                      borderColor: borderColor,
                                      textColor: textColor,
                                      hintColor: hintColor,
                                      controller: _criticalController[index],
                                      onSubmit: (value) {
                                        setState(() {
                                          aqltbl.aql![index].critical = value;
                                          _save();
                                        });
                                      },
                                    ),
                                    MyInputField(
                                      title: 'majority',
                                      hint: 'write majority ',
                                      borderColor: borderColor,
                                      textColor: textColor,
                                      hintColor: hintColor,
                                      controller: _majorController[index],
                                      onSubmit: (value) {
                                        setState(() {
                                          aqltbl.aql![index].major = value;
                                          _save();
                                        });
                                      },
                                    ),
                                    MyInputField(
                                      title: 'minority',
                                      hint: 'write minority ',
                                      borderColor: borderColor,
                                      textColor: textColor,
                                      hintColor: hintColor,
                                      controller: _minorController[index],
                                      onSubmit: (value) {
                                        setState(() {
                                          aqltbl.aql![index].minor = value;
                                          _save();
                                        });
                                      },
                                    ),
                                  ],
                                ),
                              ),
                            ],
                          );
                        }),
                  ),
                  Container(
                    height: 270,
                    width: 300,
                    margin: const EdgeInsets.only(right: 10, left: 20),
                    padding: const EdgeInsets.only(
                        left: 10, bottom: 3, right: 10, top: 5),
                    decoration: const BoxDecoration(
                      color: lightBlue,
                    ),
                    child: Column(
                      children: [
                        const Text(
                          'Summery results',
                          style: TextStyle(color: medBlueColor),
                        ),
                        Container(
                          margin: const EdgeInsets.only(top: 10, bottom: 5),
                          alignment: Alignment.centerLeft,
                          child: const Text(
                            'Results',
                            style: TextStyle(color: medBlueColor),
                          ),
                        ),

                        Container(
                          padding: const EdgeInsets.only(right: 5, left: 5),
                          decoration: BoxDecoration(
                              color: whiteColor,
                              borderRadius: BorderRadius.circular(10),
                              border: Border.all(
                                color: borderColor,
                              )),
                          child: DropdownButtonHideUnderline(
                            child: DropdownButton<String>(
                              focusColor: whiteColor,
                              value: aqltbl.result,
                              hint: const Text('select result'),
                              isExpanded: true,
                              iconSize: 36,
                              icon: const Icon(Icons.arrow_drop_down),
                              items: resultsFld.map((res) {
                                return DropdownMenuItem<String>(
                                  value: res,
                                  child: Text(
                                    res,
                                    style: const TextStyle(
                                        fontFamily: 'tajawal',
                                        fontSize: 15,
                                        color: medBlueColor),
                                  ),
                                );
                              }).toList(),
                              onChanged: (val) {
                                setState(() {
                                  aqltbl.result = val;
                                });
                                _save();
                              },
                            ),
                          ),
                        ),
                        // aqltbl.result = selRes;
                        MyInputField(
                          width: 300,
                          title: 'information remarks (ir)',
                          hint: '',
                          maxLines: 3,
                          borderColor: borderColor,
                          textColor: textColor,
                          hintColor: hintColor,
                          controller: _irController,
                          onSubmit: (value) {
                            aqltbl.ir = value;
                            _save();
                          },
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
            //Images Container
            Container(
              height: 400,
              padding: const EdgeInsets.all(0),
              margin: const EdgeInsets.only(bottom: 10, left: 10),
              decoration: const BoxDecoration(color: lightGrey),
              child: (aqltbl.images ?? []).isEmpty
                  ? Column(
                      children: [
                        Image.asset(
                          'images/empty-photo.jpg',
                          height: 300,
                        ),
                        Container(
                            margin: const EdgeInsets.only(top: 10),
                            child: Row(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: const [
                                Text('Click'),
                                Text(
                                  'Camera button',
                                  style: TextStyle(fontWeight: FontWeight.bold),
                                ),
                                Text(' to add new photo'),
                              ],
                            )),
                      ],
                    )
                  : ListView.builder(
                      scrollDirection: Axis.horizontal,
                      itemCount: (aqltbl.images ?? []).length,
                      itemBuilder: (context, imgIndex) {
                        String? _image =
                            (aqltbl.images ?? [])[imgIndex].name.toString();
                        inspect('aql image file');
                        File(_image).exists() == true
                            ? inspect('image exist')
                            : inspect('not exist: ' + _image);
                        inspect('_image: ' + _image);
                        if (aqltbl.images!.length >
                            _imgCommintControllers.length) {
                          _imgCommintControllers.add(TextEditingController());
                        }
                        _imgCommintControllers[imgIndex].text =
                            aqltbl.images![imgIndex].imgComment!;

                        inspect(_imgCommintControllers.length);

                        return Container(
                            margin: const EdgeInsets.only(left: 5),
                            height: 300,
                            child: Column(
                              children: [
                                Stack(
                                  children: [
                                    Image.file(
                                      File(_image),
                                      height: 300,
                                    ),
                                    Container(
                                      decoration: const BoxDecoration(
                                        color: medBlueColor,
                                      ),
                                      child: IconButton(
                                          onPressed: () {
                                            inspect('clear');
                                            String imgName =
                                                aqltbl.images![imgIndex].name ??
                                                    '';
                                            aqltbl.images!.removeAt(imgIndex);
                                            // aqltbl.images!.removeWhere(
                                            //     (item) => item.name == imgName);
                                            _imgCommintControllers
                                                .removeAt(imgIndex);
                                            setState(() {});
                                          },
                                          color: whiteColor,
                                          icon: const Icon(Icons.clear)),
                                    )
                                  ],
                                ),
                                MyInputField(
                                  title: 'Write remarks about image',
                                  hint: '',
                                  controller: _imgCommintControllers[imgIndex],
                                  onSubmit: (value) {
                                    aqltbl.images![imgIndex].imgComment = value;
                                    aqltbl.images![imgIndex].name = _image;
                                    _save();
                                  },
                                ),
                              ],
                            ));
                      }),
            ),
          ],
        ),
      ),
      // --- FloatingActionButton
      floatingActionButtonLocation: FloatingActionButtonLocation
          .centerDocked, //specify the location of the FAB
      floatingActionButton: FloatingActionButton(
        backgroundColor: medBlueColor,
        onPressed: () {
          inspect(aqltbl);
          setState(() {
            clickedCentreFAB =
                !clickedCentreFAB; //to update the animated container
          });
        },
        tooltip: "Centre FAB",
        child: Container(
          margin: const EdgeInsets.all(15.0),
          child: const Icon(Icons.send),
        ),
        elevation: 4.0,
      ),

      // --- bottom action bar
      bottomNavigationBar: BottomAppBar(
        child: Container(
          margin: const EdgeInsets.only(left: 12.0, right: 12.0),
          child: Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              //to leave space in between the bottom app bar items and below the FAB
              IconButton(
                //update the bottom app bar view each time an item is clicked
                onPressed: () {
                  // updateTabSelection(0, "Home");
                  Get.to(const MainMenu());
                },
                iconSize: 27.0,
                icon: Image.asset(
                  'images/logo.png',
                  color: medBlueColor,
                ),
              ),

              const SizedBox(
                width: 50.0,
              ),
              IconButton(
                onPressed: () async {
                  // updateTabSelection(2, "Incoming");
                  await _takeImage('gallery');
                },
                iconSize: 27.0,
                icon: const Icon(
                  Icons.image_outlined,
                  color: medBlueColor,
                ),
              ),
              IconButton(
                onPressed: () async {
                  // updateTabSelection(1, "Outgoing");
                  await _takeImage('camera');
                },
                iconSize: 27.0,
                icon: const Icon(
                  Icons.camera_alt,
                  color: medBlueColor,
                ),
              ),
            ],
          ),
        ),
        //to add a space between the FAB and BottomAppBar
        shape: const CircularNotchedRectangle(),
        //color of the BottomAppBar
        color: Colors.white,
      ),
    );
  }

  _save() {
    inspect('submit');
    saveAql(shipmentId, aqltbl);
    box.write('aql'+shipmentId.toString(), aqltbl);
  }

  _takeImage(method) async {
    String _imgPath = await imageFromDevice(method);
    if (_imgPath != empty) {
      ImagesModel imgMdl = ImagesModel();
      imgMdl.name = _imgPath;
      imgMdl.imgComment = '';
      if (aqltbl.images != null) {
        // _saveLocaly(close: 0);
        setState(() {
          aqltbl.images!.add(imgMdl);
          _save();
        });
      }
    }
  }

  Future _sendAqlToServer() async {
    try {
      var response = await http.post(urlSendProductPhoto, body: {
        'aql': json.encode(aqltbl).toString(),
        'id': shipmentId.toString(),
      });
      if (response.statusCode == 200) {
        Get.snackbar('Success', 'Image successfully uploaded');
        return response.body;
      } else {
        Get.snackbar('Fail', 'Image not uploaded');
        inspect('Request failed with status: ${response.statusCode}.');
        return 'empty';
      }
    } catch (socketException) {
      Get.snackbar('warning', 'Image not uploaded');
      return 'empty';
    }
  }

}