Angular Material checkboxes with intermediate state based on JSON structure
I'm trying to implement tree menu with check boxes, that is based on object and the flow is supposed to go like:
unchecked -> checked (tick) -> intermediate (-) -> unchecked -> ...
But this is how it actually behaves:
unchecked -> checked (tick) -> intermediate (-) -> checked -> intermediate -> checked -> ...
The problem is, it never goes back to unchecked state. Problem demonstration: https://stackblitz.com/edit/ng-matcheckbox-from-json?file=src/app/app.component.html
Tags structure:
structuredTags = {
group1: {
tag1: { included: false, excluded: false },
tag2: { included: false, excluded: false }
},
group2: {
tag3: { included: false, excluded: false },
tag4: { included: false, excluded: false }
}
};
Items on the list have multiple tags groups, but I only care about tag names, not group names. I try to use [checked] and [intermediate] attributes like so:
<ul>
<li *ngFor="let group of structuredTags | keyvalue">
<mat-checkbox>
{{group.key}}
</mat-checkbox>
<ul>
<li *ngFor="let tag of group.value | keyvalue">
<mat-checkbox (change)="toggleTag($event.checked, group.key, tag.key)"
[checked]="tag.value.included"
[indeterminate]="tag.value.excluded">
{{tag.key}}
</mat-checkbox>
</li>
</ul>
</li>
</ul>
I also tried using 2 sets and adding/deleting values to/from them and then in HTML use:
[checked]="selectedTags.has(tag.value)" [indeterminate]="excludedTags.has(tag.value)"
But it doesn't work as supposed to either. I think I'm missing something, any help will be much appreciated.
See also questions close to this topic
-
Creating two value range slider from Angular material native component
I need a two value range slider for my app, however none of the packages that I've looked at on NPM etc are 100% suitable for what I need. The Angular Material slider is the most suitable, however it doesn't allow for two values to be used on a single slider.
To get around this, I've had an idea of placing one slider on top of the other, to give the impression of one slider with two values. This works well, and has a smooth behaviour which is one of the requirements that I wanted my slider to have.
However, I would also like to add a bar in between the two slider thumbs, so that the selected range is highlighted and visible. The native slider does have this, but since it only allows one value the highlight starts from 0 and extends to the value of the slider.
Instead I want to have the highlight between the upper and lower values of the thumbs on the slider. But I have no idea how to add this to it. So I was wondering if someone could help me out. I'm not entirely sure if I'd need to add a new element on top of the bar that adjusts to the size between the two thumbs or if I'd have to do something different.
Alternatively if anyone knows how to make NGX-slider allow a smooth step like the angular material slider that would be the best solution and I'd love to hear it. https://www.npmjs.com/package/@angular-slider/ngx-slider
https://angular-9-material-starter-5ueh7p.stackblitz.io
Code so far
<mat-slider class="slider-left"></mat-slider> <mat-slider class="slider-right"></mat-slider> .slider-right { position: relative; left: -128px; } ::ng-deep .mat-slider-track-fill { background-color: rgba(0, 0, 0, 0.26) !important; } ::ng-deep .mat-slider-track-background { background-color: rgba(0, 0, 0, 0.26); }
-
Angular 10 form action not getting variable
I am creating a form in angular, used from a 3rd party, which needs to redirect away from my site for a payment and back.
I have added their sample code (the form which does a post) into my angular app and added a formGroup, and an action to the form (the action is the url I want to redirect to).
<form [formGroup]="tdsvt" (ngSubmit)="onSubmit2021" method="post" id="redirectForm" action="{{redirectUrl}}"> <input type="hidden" name="id" formControlName="reqID" /> </form>
I have changed the action to the variable that is needed, but it does not redirect and it stays blank. I have tried doing a normal post request and subscribe like so:
return this.http.post<any>(redirectUrl, data);
But I am hit with a CORS issue as it is a total different URL.
How can I get the action to work as a variable and redirect? Or if I shouldn't use an action, what's the best method around this?
Thank you
-
Child route with fragment
I have a page with a side menu, each side menu item has a routerLink that sends a different fragment. I want to know if it is possible that this new route with the fragment has a child route.
Example:
Side menu:
<button type="button" routerLink="['/pageA']" fragment="frag">btn side menu</button>
On click this button, the route would look like this: http://localhost:4200/#/pageA#frag
Content Page
<button type="button" routerLink="['child-a']">A</button> <button type="button" routerLink="['child-b']">B</button> <router-outlet></router-outlet> // Here son A or son B will be loaded
And when click on button A, the route would look like this: http://localhost:4200/#/pageA#frag/child-a
page-routing.module.ts
const routes: Routes = [ { path: '', component: PageAComponent, children: [ { path: 'child-a', component: ChildAComponent, }, { path: 'child-b', component: ChildBComponent, }, ], }, ];
-
setting a type only for the value of an object
I have this object:
const theme = {}
This object is being filled by a function, this function adds a property to this object whenever it's called, the key it sets is a random number as a string, so "1", "31" and so on, and the value it sets is a string.
I was looking for something like this in TypeScript:
interface Theme { string: string } const theme: Theme = {} const theFunction(){ const key = `${Math.floor(Math.random() * 1000)}`; const value = "value"; theme[key] = value; }
The theFunction might get called at any unknown time,
-
How to format "2021-01-19T12:50:00Z" to: 2021-01-19 12:50:00
I am using angular and rxjs.
So I have this:
x: console.log(res.map(date => date.dt))
And it returns this:
0: "2021-01-19T12:50:00Z" 1: "2021-01-19T12:51:00Z" 2: "2021-01-19T12:52:00Z" 3: "2021-01-19T12:53:00Z" 4: "2021-01-19T12:54:00Z" 5: "2021-01-19T12:55:00Z" 6: "2021-01-19T12:56:00Z" 7: "2021-01-19T12:57:00Z" 8: "2021-01-19T12:59:00Z"
But of course that is not readable.
SO I want to convert it to for example this: '2021-01-19 12:50:00',
So: yyyy-MM-dd HH-MM-SS
But so what I have to change?
Thank you
-
C# WinForm ListView with checkboxes at some items only
I'm using ListView Control.
Need to have checkboxes with a half of the items only.
I see listView1.CheckBoxes property. Looks it refers to all the items.
Is there some easy way how I can make the checkboxes with specified Items only ? -
Return textbox value if checkbox is selected
I have a form where the user can select items using checkboxes and enter the quantity of the item they want. Is there a way to return only the quantity of the items that have their checkbox selected. Currently,
req.body.qty
retrieves the quantity values for all items even if their checkbox is not selected.<% availableFood.forEach(function(food_item){ %> <tr> <td><input type="checkbox" name="checkbox[]" value= <%= food_item.name %>></td> <td><input id="qty" type="text" name="qty" value="1" style="width: 30px;"/></td> <td><%= food_item.name %></td> <td><%= food_item.typical_values %></td> <td><%= food_item.unit_of_the_typical_value %></td> <td><%= food_item.calories %></td> <td><%= food_item.carbs %></td> <td><%= food_item.fat %></td> <td><%= food_item.protein %></td> <td><%= food_item.salt %></td> <td><%= food_item.sugar %></td> </tr> <% }) %>
-
how to get selected/unselected data inside a fragment where checkbox inside an adapter within an adapter?
I have a product detail which contains some list of variation and inside of variations I have another list of variation options.
"product": { "id": 1, "name": "Rangs 2 Ton Inverter AC", "price": 99900, "variations": [ { "id": 2, "title": "Color", "required": true, "selection_type": 2, "options": [ { "id": 5, "name": "White", "price": 100, "price_type": 1 }, { "id": 6, "name": "Black", "price": 500, "price_type": 1 }, { "id": 7, "name": "Red", "price": 50, "price_type": 1 }, { "id": 8, "name": "Cream", "price": 0, "price_type": 1 } ] }, { "id": 3, "title": "size", "required": true, "selection_type": 1, "options": [ { "id": 9, "name": "2", "price": 1000, "price_type": 1 }, { "id": 10, "name": "5", "price": 10000, "price_type": 1 }, { "id": 11, "name": "10", "price": 15000, "price_type": 1 } ] }, { "id": 4, "title": "Box", "required": true, "selection_type": 1, "options": [ { "id": 12, "name": "below 50 kg", "price": 10, "price_type": 2 }, { "id": 13, "name": "over 50 kg", "price": 15, "price_type": 2 } ] } ] }
My model class
public class Variation { private int id; private String title; private boolean isRequired; private int type; private ArrayList<VariationOption> variationOptionArrayList; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public boolean isRequired() { return isRequired; } public void setRequired(boolean required) { isRequired = required; } public int getType() { return type; } public void setType(int type) { this.type = type; } public ArrayList<VariationOption> getVariationOptionArrayList() { return variationOptionArrayList; } public void setVariationOptionArrayList(ArrayList<VariationOption> variationOptionArrayList) { this.variationOptionArrayList = variationOptionArrayList; } @Override public String toString() { return "Variation{" + "id=" + id + ", title='" + title + '\'' + ", isRequired=" + isRequired + ", type=" + type + ", variationsOptionArrayList=" + variationOptionArrayList + '}'; } }
My other model class
public class VariationOption { private int id; private String name; private double price; private int priceType; private boolean isChecked; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public int getPriceType() { return priceType; } public void setPriceType(int priceType) { this.priceType = priceType; } public boolean isChecked() { return isChecked; } public void setChecked(boolean checked) { isChecked = checked; } }
variation options are checkboxes. My goal is to set the data and get the selected variation options inside the fragment.
What I have tried
I used two adapters to represent data inside UI.
The first adapter for variation contains another recycler view and another adapter for variation options.
Variation list adapter
public class ProductVariationListAdapter extends RecyclerView.Adapter<ProductVariationListAdapter.ViewHolder> { private Context context; private ArrayList<Variation> variationArrayList; public ProductVariationListAdapter(Context context, ArrayList<Variation> variationArrayList) { this.context = context; this.variationArrayList = variationArrayList; } @NonNull @Override public ProductVariationListAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_each_row_product_variation, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(@NonNull ProductVariationListAdapter.ViewHolder holder, int position) { Variation variation = variationArrayList.get(position); holder.labelProductVariationTitle.setText(variation.getTitle()); if (variation.isRequired()) { holder.labelProductVariationRequired.setVisibility(View.VISIBLE); } else { holder.labelProductVariationRequired.setVisibility(View.GONE); } LinearLayoutManager layoutManager = new LinearLayoutManager(context); holder.recyclerViewProductVariationOption.setLayoutManager(layoutManager); holder.recyclerViewProductVariationOption.setHasFixedSize(true); holder.recyclerViewProductVariationOption.setNestedScrollingEnabled(false); ProductVariationOptionListAdapter adapter = new ProductVariationOptionListAdapter(context, variation.getVariationOptionArrayList()); holder.recyclerViewProductVariationOption.setAdapter(adapter); } @Override public int getItemCount() { return variationArrayList.size(); } public class ViewHolder extends RecyclerView.ViewHolder { private TextView labelProductVariationTitle; private TextView labelProductVariationRequired; private RecyclerView recyclerViewProductVariationOption; public ViewHolder(@NonNull View itemView) { super(itemView); labelProductVariationTitle = itemView.findViewById(R.id.labelProductVariationTitle); labelProductVariationRequired = itemView.findViewById(R.id.labelProductVariationRequired); recyclerViewProductVariationOption = itemView.findViewById(R.id.recyclerViewProductVariationOption); } } }
variation option list adapter
public class ProductVariationOptionListAdapter extends RecyclerView.Adapter<ProductVariationOptionListAdapter.ViewHolder> { private Context context; private ArrayList<VariationOption> variationOptionArrayList; public ProductVariationOptionListAdapter(Context context, ArrayList<VariationOption> variationOptionArrayList) { this.context = context; this.variationOptionArrayList = variationOptionArrayList; } @NonNull @Override public ProductVariationOptionListAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_each_row_product_variations_option, parent, false); return new ProductVariationOptionListAdapter.ViewHolder(view); } @Override public void onBindViewHolder(@NonNull ProductVariationOptionListAdapter.ViewHolder holder, int position) { VariationOption variationOption = variationOptionArrayList.get(position); holder.tvOptionPricing.setText(variationOption.getPrice() + " " + context.getResources().getString(R.string.bdt)); holder.checkBoxOption.setText(variationOption.getName()); if (variationOption.isChecked()) { holder.checkBoxOption.setChecked(true); } else { holder.checkBoxOption.setChecked(false); } } @Override public int getItemCount() { return variationOptionArrayList.size(); } public class ViewHolder extends RecyclerView.ViewHolder { private final CheckBox checkBoxOption; private final TextView tvOptionPricing; public ViewHolder(@NonNull View itemView) { super(itemView); checkBoxOption = itemView.findViewById(R.id.checkBoxOption); tvOptionPricing = itemView.findViewById(R.id.tvOptionPricing); //checkbox click event handling checkBoxOption.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { Toast.makeText(context, "selected " + checkBoxOption.getText(), Toast.LENGTH_LONG).show(); } else { Toast.makeText(context, "unselected " + checkBoxOption.getText(), Toast.LENGTH_LONG).show(); } } }); } }
so how can I achieve selected and unselected listener inside fragment or how can I achieve this feature?
-
How can I display a select list within an Angular Material table?
How can I display a select list within an Angular Material table?
error:
TS2339: Property 'element' does not exist on type 'MyaccountComponent'. <mat-option *ngFor="let role of element.validRoles" [value]="role.value">
I get the same error if I change
element.validRoles
tovalidRoles
too.Component:
export class MyaccountComponent implements OnInit { displayedColumns: string[] = ['email', 'role', 'rolestatus', 'validRoles']; dataSource = []; ngOnInit(){ this.getAllUsers(); } constructor(private userService: UserService) { } getAllUsers(){ const obs = this.userService.getAllRegisteredUsers(); obs.subscribe(data => { console.log(data.users); this.dataSource = data.users }); } }
Template:
<ng-container matColumnDef="validRoles"> <th mat-header-cell *matHeaderCellDef> Assign Role</th> <mat-form-field appearance="fill"> <mat-label>Roles</mat-label> <mat-select> <mat-option *ngFor="let role of element.validRoles" [value]="role.value"> {{role.viewvalue}} </mat-option> </mat-select> </mat-form-field> </ng-container>
My data is in the format:
data.users.validRoles = [ {value: "admin", viewvalue: "Admin"} ];
-
Trigger AngularComponent-constructor on startup with PreLoadingStrategy
The goal: trigger a component residing in a module, so my subscription in the ctor of the component is activated. I'm using PreloadAllModules as a preloadingStrategy. But it's not happening.
I need to subscribe to some events in de constructor of my FriendsComponent. the setup is like this:
FriendsComponent is shown in the template of the SocialComponent, which is part of the SocialModule.
social.component.html
<div> <friends-component></friends-component> </div>
the SharedModule declares the FriendsComponent. AppModule imports SharedModule, RouterModule for AppModule is like this:
{ path: 'social', component: SocialModule, children: [ { path: 'friends', component: FriendsComponent } ] },
I think the problem is because the FriendsComponent is not part of a router-outlet? Can it be done without a router-outlet?
If a module would be pre- or eager loaded, would it automatically trigger the constructors (and the subscription)? Is the issue with my preloading strategy?
I have tried adding: data:{preload:true} to the paths declared in routermodule.
Everything works fine, when the user activates the SocialModule (for instance by clicking on a button with a routerLink to social/friends), but I want it activated on startup (just not shown on any html) I'm working with Angular Ivy, but think I'm still missing the points. Any help is appreciated