Does changing an item inside a list will trigger the state change in Riverpod Flutter? - riverpod

I have a list of products and want to change some fields inside list. I am curious if this change can be emitted with Riverpod in Flutter. It seems it is not working even I use ref.watch for the provider.
#freezed
class ApplicationState with _$ApplicationState {
const factory ApplicationState({
#Default([]) List<Product> products,
}) = _ApplicationState;
}
class ApplicationNotifier extends StateNotifier<ApplicationState> {
ApplicationNotifier() : super(const ApplicationState());
setProductQuantity({required int i, required String productId}) {
final changedProduct = state.products
.map((product) => product.id == productId
? Product(
id: product.id,
title: product.title,
price: product.price,
description: product.description,
availableQuantity: product.availableQuantity,
quantity: i,
)
: product)
.toList();
state = state.copyWith(products: changedProduct);
}
}

Try like this:
state = ApplicationState(products: changedProduct);
instead of
state = state.copyWith(products: changedProduct);

Related

Update list Aspnet core 2.2

I would like to update a list of items most do not know how to do, when my only method adciona new items to existing inves change.
save change
public async Task<CommandResult> ExecuteAsync(EventsCommandsHandler handler)
{
var listItens = await handler.DbContext.ListItens
.Where(f => f.Id == this.Id)
.SingleOrDefaultAsync();
listItens.SetData(
name: Name,
description: Description
);
handler.DbContext.ListItens.Update(listItens);
if (Items.Length > 0)
{
var itens = Items
.Select(p => p.ToItemList(listItens.Id))
.Where(p => p != null)
.ToArray();
await handler.DbContext.ItemsList.(itens);
}
var rows = await handler.DbContext.SaveChangesAsync();
return await Task.FromResult(new CommandResult(rows));
}
create intens
public static ItemList ToItemList(this ItemCommand command, string listId)
{
if (string.IsNullOrWhiteSpace(command.Description))
return null;
var itens = new ItemList(
id: String.IsNullOrWhiteSpace(command.Id) ? RandomId.NewId(8) : command.Id,
description: command.Description,
listId: listId
);
return itens;
}
I need a way for this method.
I have a list and this list has items, when I edit the list, I want to be able to delete, edit or add more items.
You have a To-Do list. There should be an add button.
A post request should be sent and data should be written to the database, and page - updated when you press any button like remove, edit and add.
If you want it to be async, then you should use JavaScript or Blazor.

how to return selected columns based on user choice

I'm trying to limit which fields are returned by an API based on a parameter called fields which I accept multiple strings doing this
private readonly string[] fields;
public string[] SelectiveSerializer(string fields)
{
string[] _fields;
var fieldColl = fields.Split(',');
_fields = fieldColl
.Select(f => f.ToLower().Trim())
.ToArray();
return _fields;
}
I want to be able to choose what I return based on whatever the user gives me in _fields. Normal way to do it:
var linq = (from entity in db.users
where entity.ID== id
&& entity.ON== false
select( new {
ID = entity.ID,
FirstName = entity.FirstName,
LastName =entity.LastName,
FotherName = entity.FotherName
}).ToList();
but here I have to specify the fields in Select (ID, FirstName ..etc), which I want it to be dynamic based on what fields[] has. Is there a way to do this?
sort of this (which is wrong):
var linq = (from entity in db.users
where entity.ID== id
&& entity.ON== false
select( new {
foreach (string s in _fields)
{
entity.s;
}
}).ToList();
Use a ternary expression for each assignment
var user = entityContext.Users.Where(u => u.ID == id)
.Select(u => new {
ID = _fields.Contains['id'] ? u.ID : 0,
FirstName = _fields.Contains['firstname'] ? u.FirstName : null,
LastName = _fields.Contains['lastname'] ? u.LastName : null,
otherName = _fields.Contains['othername'] ? u.otherName : null
})
.ToList();
I also would put the field names in a HashSet<string> for a better performance.
var _fields = new HashSet<string>(fields.Split(',').Select(f => f.ToLower().Trim()));
This solution keeps all the properties but sets the unwanted ones to null. If you want to dynamically add properties, see this other SO question: How to dynamically create a class in C#?. But note that this only useful in scenarios where objects of this type are processed dynamically as well.
I was finally able to do this with minimal work.
assuming the filter is a string list. string array.
so to avoid reflection and all that jazz, I iterate over each record and see if the variable is in the filter list, then create a dic entry with (var,val) assuming that no duplicate var in the same record, which can be catch if you want but I don't have this issue.
Then at the end add that dic to a list.
the method accept anonymous type list and a filter list.
public static List<Dictionary<string, object>> filteredList(IEnumerable source, string[] filter)
{
var filteredList = new List<Dictionary<string, object>>();
foreach (var single in source)
{
var type = single.GetType();
var props = type.GetProperties();
var singleRecord = new Dictionary<string, object>();
foreach (var v in props)
{
if (filter.Contains(v.Name))
{
var tempValue = type.GetProperty(v.Name).GetValue(single, null);
singleRecord.Add(v.Name, tempValue);
}
}
filteredList.Add(singleRecord);
}
return filteredList;
}

passing dynamic model in MVC5 Razor View [duplicate]

This question already has answers here:
Dynamic Anonymous type in Razor causes RuntimeBinderException
(12 answers)
Closed 6 years ago.
I'm trying to pass dynamic results to View from Controller, method ShowColor returns dynamic results. In View I try to loop through the collection but I'm getting error
'object' does not contain a definition for 'ColorID'.
I have the following code in Controller and View
public class myColor
{
public int ID { get; set; }
public string Name { get; set; }
public string Like { get; set; }
}
public dynamic ShowColor()
{
IList<myColor> color = new List<myColor>();
color.Add(new myColor { ID = 1, Name = "Red", Like = "***" });
color.Add(new myColor { ID = 2, Name = "Green", Like = "*****" });
color.Add(new myColor { ID = 3, Name = "Blue", Like = "**" });
color.Add(new myColor { ID = 4, Name = "Yellow", Like = "*" });
var select = (from c in color
select new
{
ColorID = c.ID,
ColorName = c.Name
}).ToList();
return select;
}
public ActionResult DBDynamic()
{
return View(ShowColor());
}
View
#model dynamic
#{
ViewBag.Title = "DBDynamic";
}
<h2>DBDynamic</h2>
<p>
<ul>
#foreach (var m in Model)
{
<li> #m.ColorID</li>
}
</ul>
</p>
Found the solution here and a nice blog here:
public static ExpandoObject ToExpando(this object anonymousObject)
{
IDictionary<string, object> expando = new ExpandoObject();
foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(anonymousObject))
{
var obj = propertyDescriptor.GetValue(anonymousObject);
expando.Add(propertyDescriptor.Name, obj);
}
return (ExpandoObject)expando;
}
And call it like this
var select = (from c in color
select new
{
ColorID = c.ID,
ColorName = c.Name
})
.AsEnumerable()
.Select(x => x.ToExpando());
return View(select);
An anonymous object is not the same thing as a dynamic. If you want to use it like a dynamic then cast it to that:
#foreach (dynamic m in Model)
However, dynamics are best avoided if at all possible. You lose all compile-time checking and even intellisense. You won't know if you fat-fingered a property name until runtime or even if you've accidentally used the wrong type of thing the wrong way until runtime. If something is broken, you want to know about it at compile-time, not when it's already live and affecting users, when you may not even know that an error has occurred unless a user notifies you. That's a horrible situation for your app to be in.
Long and short, use strong types. If you want something with properties, ColorID and ColorName, create a view model with those properties and select your query into instances of that type. Then, everything will be nice and strongly-typed and you'll know well in advance if there's some error or problem with your code.

How to perform these operations for the "List": map, group, lookup, aggregate, sort?

I have the List of categories and their products and I want to perform these operations:
Map
Group
Lookup
Query aggregate functions
Sorting by multiple fields
How this can be done in Dart?
void main() {
var books = new Category(0, "Books");
var magazines = new Category(1, "Magazines");
var categories = [books, magazines];
var products = [
new Product(0, "Dr. Dobb's", magazines),
new Product(1, "PC Magazine", magazines),
new Product(2, "Macworld", magazines),
new Product(3, "Introduction To Expert Systems", books),
new Product(4, "Compilers: Principles, Techniques, and Tools", books),
];
// How to map product list by id?
// How to group product list by category?
// How to create lookup for product list by category?
// How to query aggregate functions?
// How to sort product list by category name and product name?
}
class Category {
int id;
String name;
Category(this.id, this.name);
operator ==(other) {
if(other is Category) {
return id == other.id;
}
return false;
}
String toString() => name;
}
class Product {
int id;
String name;
Category category;
Product(this.id, this.name, this.category);
operator ==(other) {
if(other is Product) {
return id == other.id;
}
return false;
}
String toString() => name;
}
These lists are similar to records in data tables.
Mapping can be done with the .map method, like so:
products.map((product) => product.id)
This will return a list of the product ids.
Grouping would be done with the fold method. For example, if you wanted to group products by category:
product.fold<Map<String, List<Product>>>({}, (productMap, currentProduct) {
if (productMap[currentProduct.category.name] == null) {
productMap[currentProduct.category.name] = [];
}
productMap[currentProduct.category.name].add(currentProduct);
return productMap;
});
Lookup is done with .firstWhere. For example:
products.firstWhere((product) => product.category.name == 'books');

How can I add an item to a SelectList in ASP.net MVC

Basically I am looking to insert an item at the beginning of a SelectList with the default value of 0 and the Text Value of " -- Select One --"
Something like
SelectList list = new SelectList(repository.func.ToList());
ListItem li = new ListItem(value, value);
list.items.add(li);
Can this be done?
There really isn't a need to do this unless you insist on the value of 0. The HtmlHelper DropDownList extension allows you to set an option label that shows up as the initial value in the select with a null value. Simply use one of the DropDownList signatures that has the option label.
<%= Html.DropDownList( "DropDownValue",
(IEnumerable<SelectListItem>)ViewData["Menu"],
"-- Select One --" ) %>
I got this to work by Populating a SelectListItem, converting to an List, and adding a value at index 0.
List<SelectListItem> items = new SelectList(CurrentViewSetups, "SetupId", "SetupName", setupid).ToList();
items.Insert(0, (new SelectListItem { Text = "[None]", Value = "0" }));
ViewData["SetupsSelectList"] = items;
This is possible.
//Create the select list item you want to add
SelectListItem selListItem = new SelectListItem() { Value = "null", Text = "Select One" };
//Create a list of select list items - this will be returned as your select list
List<SelectListItem> newList = new List<SelectListItem>();
//Add select list item to list of selectlistitems
newList.Add(selListItem);
//Return the list of selectlistitems as a selectlist
return new SelectList(newList, "Value", "Text", null);
I liked #AshOoO's answer but like #Rajan Rawal I needed to preserve selected item state, if any. So I added my customization to his method AddFirstItem()
public static SelectList AddFirstItem(SelectList origList, SelectListItem firstItem)
{
List<SelectListItem> newList = origList.ToList();
newList.Insert(0, firstItem);
var selectedItem = newList.FirstOrDefault(item => item.Selected);
var selectedItemValue = String.Empty;
if (selectedItem != null)
{
selectedItemValue = selectedItem.Value;
}
return new SelectList(newList, "Value", "Text", selectedItemValue);
}
private SelectList AddFirstItem(SelectList list)
{
List<SelectListItem> _list = list.ToList();
_list.Insert(0, new SelectListItem() { Value = "-1", Text = "This Is First Item" });
return new SelectList((IEnumerable<SelectListItem>)_list, "Value", "Text");
}
This Should do what you need ,just send your selectlist and it will return a select list with an item in index 0
You can custome the text,value or even the index of the item you need to insert
Here html helper for you
public static SelectList IndividualNamesOrAll(this SelectList Object)
{
MedicalVarianceViewsDataContext LinqCtx = new MedicalVarianceViewsDataContext();
//not correct need individual view!
var IndividualsListBoxRaw = ( from x in LinqCtx.ViewIndividualsNames
orderby x.FullName
select x);
List<SelectListItem> items = new SelectList (
IndividualsListBoxRaw,
"First_Hospital_Case_Nbr",
"FullName"
).ToList();
items.Insert(0, (new SelectListItem { Text = "All Individuals",
Value = "0.0",
Selected = true }));
Object = new SelectList (items,"Value","Text");
return Object;
}
The .ToList().Insert(..) method puts an element into your List. Any position can be specified. After ToList just add .Insert(0, "- - First Item - -")
Your code
SelectList list = new SelectList(repository.func.ToList());
New Code
SelectList list = new SelectList(repository.func.ToList().Insert(0, "- - First Item - -"));
May not sound very elegant, but I usually do something like this:
var items = repository.func.ToList();
items.Insert(0, new funcItem { ID = 0, TextValue = "[None]" });
ViewBag.MyData = new SelectList(items);
Okay I like clean code so I made this an extension method
static public class SelectListHelper
{
static public SelectList Add(this SelectList list, string text, string value = "", ListPosition listPosition = ListPosition.First)
{
if (string.IsNullOrEmpty(value))
{
value = text;
}
var listItems = list.ToList();
var lp = (int)listPosition;
switch (lp)
{
case -1:
lp = list.Count();
break;
case -2:
lp = list.Count() / 2;
break;
case -3:
var random = new Random();
lp = random.Next(0, list.Count());
break;
}
listItems.Insert(lp, new SelectListItem { Value = value, Text = text });
list = new SelectList(listItems, "Value", "Text");
return list;
}
public enum ListPosition
{
First = 0,
Last = -1,
Middle = -2,
Random = -3
}
}
Usage (by example):
var model = new VmRoutePicker
{
Routes =
new SelectList(_dataSource.Routes.Select(r => r.RouteID).Distinct())
};
model.Routes = model.Routes.Add("All", "All", SelectListHelper.ListPosition.Random);
//or
model.Routes = model.Routes.Add("All");
As this option may need in many different manners, i reached to conclusion to develop an object so that it can be used in different scenarios and in future projects
first add this class to your project
public class SelectListDefaults
{
private IList<SelectListItem> getDefaultItems = new List<SelectListItem>();
public SelectListDefaults()
{
this.AddDefaultItem("(All)", "-1");
}
public SelectListDefaults(string text, string value)
{
this.AddDefaultItem(text, value);
}
public IList<SelectListItem> GetDefaultItems
{
get
{
return getDefaultItems;
}
}
public void AddDefaultItem(string text, string value)
{
getDefaultItems.Add(new SelectListItem() { Text = text, Value = value });
}
}
Now in Controller Action you can do like this
// Now you can do like this
ViewBag.MainCategories = new SelectListDefaults().GetDefaultItems.Concat(new SelectList(db.MainCategories, "MainCategoryID", "Name", Request["DropDownListMainCategory"] ?? "-1"));
// Or can change it by such a simple way
ViewBag.MainCategories = new SelectListDefaults("Any","0").GetDefaultItems.Concat(new SelectList(db.MainCategories, "MainCategoryID", "Name", Request["DropDownListMainCategory"] ?? "0"));
// And even can add more options
SelectListDefaults listDefaults = new SelectListDefaults();
listDefaults.AddDefaultItme("(Top 5)", "-5");
// If Top 5 selected by user, you may need to do something here with db.MainCategories, or pass in parameter to method
ViewBag.MainCategories = listDefaults.GetDefaultItems.Concat(new SelectList(db.MainCategories, "MainCategoryID", "Name", Request["DropDownListMainCategory"] ?? "-1"));
And finally in View you will code like this.
#Html.DropDownList("DropDownListMainCategory", (IEnumerable<SelectListItem>)ViewBag.MainCategories, new { #class = "form-control", onchange = "this.form.submit();" })
A work-around is to use #tvanfosson's answer (the selected answer) and use JQuery (or Javascript) to set the option's value to 0:
$(document).ready(function () {
$('#DropDownListId option:first').val('0');
});
Hope this helps.
Try something like the following code:
MyDAO MyDAO = new MyDAO();
List<MyViewModel> _MyDefault = new List<MyViewModel>() {
new MyViewModel{
Prop1= "All",
Prop2 = "Select all"
}
};
ViewBag.MyViewBag=
new SelectList(MyDAO
.MyList().Union(
_MyDefault
), "Prop1", "Prop2");
I don't if anybody else has a better option...
<% if (Model.VariableName == "" || Model.VariableName== null) { %>
<%= html.DropDpwnList("ListName", ((SelectList) ViewData["viewName"], "",
new{stlye=" "})%>
<% } else{ %>
<%= html.DropDpwnList("ListName", ((SelectList) ViewData["viewName"],
Model.VariableName, new{stlye=" "})%>
<% }>

Resources