A merchant has multiple branches.
When selecting a merchant I'm trying to make another dropdown list the data from merchant.branches.
Doing the below does not seem to be resolving the problem:
<label>Merchant:</label>
<select ng-if="merchants" ng-model="merchant" ng-options="merchant.name for merchant in merchants track by merchant.id"></select>
<span ng-if="!merchants">Listing merchants, please wait...</span>
<br />
<label>Branch:</label>
<select ng-if="merchant.branches" ng-model="device.branch" ng-options="branch.name for branch in merchant.branches track by branch.id"></select>
<span ng-if="!merchant.branches">Listing branches, please wait...</span>
<pre>
{{ merchant.branches }}
</pre>
Please note that the data is correct and Merchants return properly with their respective branches.
SOLVED
Using a different method (By calling ng-change on the first dropdown and then populating the second dropdown). However, is it possible to achieve this without writing any controller code?
I have to guess at how your controller works, but you might have luck with this:
<label>Branch:</label>
<select ng-if="merchant.branches"
ng-model="device.branch"
ng-options="branch.name for branch in merchants[merchant.id].branches track by branch.id"></select>
Related
To begin with, I am an absolute beginner in front-end development, thus please excuse me if the question is too elementary.
The project I am working on, a drop-down list has been defined as:
<div ng-controller="FacetController">
<div class="spnlocationdrop-container" ng-hide="isservicelocal">
<select class="spnlocationdrop" ng-model="$parent.locationsearch" ng-options="location for location in locations | sortArray ">
<option value="">All Cities</option>
</select>
</div>
</div>
The list contains cities, out-of which the user has to select one. The value has to be stored, and sent to the backend via an AJAX call.
How do I get the selected value? Until now, I've been doing that using the document.getElementByID().value() function, but since the above list contains no ID, how do I get the value?
ng-model will have the value of the option selected.
Here's a simple working example: Plunker
In my example, data.singleSelect has the value you need so I'm able to output that to the view using {{ data.singleSelect }} though if I wanted to access it in my controller I would do var input = $scope.data.singleSelect and then pass that input variable to the backend via an AJAX call.
I was under the impression that trackBy function is used only when trying to optimize the performance of *ngFor, so that if something changes, the DOM doesn't have to be rebuild.
However, recently, I came across a situation when trackBy actually fixed a wrong behavior.
Take this for example: https://plnkr.co/edit/nRgdwoiKAMpsbmWaoMoj?p=preview
Focus on Hobbies section, especially HTML:
<div>
<h2>Hobbies</h2>
<div *ngFor="let h of user.hobbies; trackBy:customTrackBy; let i = index">
#{{i}} - {{h | json}}<br />
<input [(ngModel)]="h.name" name="hobby_name_{{i}}" /> <br /><br />
<select [(ngModel)]="h.type_id" name="type_{{i}}">
<option *ngFor="let t of types" [value]="t.id">{{t.type}}</option>
</select>
<br />
<br />
<button class="btn btn-warn" (click)="remove(i)">Remove</button>
<br /><br />
</div>
</div>
I had to explicitly define this part: trackBy:customTrackBy in the first *ngFor. If trackBy is removed, and the following steps are performed:
remove the first item
add a new item
In this case, the inputs of the first item get replaced with the content of the second item (both fields have the same content), however, the values in the model are correct.
trackBy solves this issue, but why?
I would really appreciate any kind of explanation. If this is not the right place to ask this kind of questions please redirect me to the correct one. Thanks.
update
Here's an example of the wrong behavior: https://plnkr.co/edit/u8YajKfHcPiVqY0WcJt7?p=preview remove the first item (cycling) and add a new item (add button) and see how both values get the same default value (BF will get replaced by "default value" even though the model stays correct).
*ngFor by default tracks items by object identity.
If you have primitive values like an array of strings, and use them in
<div *ngFor="let item of items; let i=index">
<input [(ngModel)]="item" name="item{{i}}">
</div>
and you edit one item, then *ngFor gets in trouble, because the identity of the edited item has changed.
With ngForTrackBy you can tell *ngFor to track the item by index, then above code will work fine when you edit fields.
Another use case is when you want *ngFor to track items by some custom object id property instead of the object identity.
I have lots of models and show them in tables. When user needs to do something with several models, we need to give him ability to choose rows.
How can I implement it with checkboxes? Of course I don't want to create special field on my models for every table.
This is simple example.
https://ember-twiddle.com/0b8f429f6ad3e0572438
My tries were:
{{input type='checkbox' checked=model.someNotExistedField}}
But in this case input just doesnt work.
And:
<input type="checkbox" {{action marked model}} checked={{in-arr record selectedItems}} />
In second example I've tried to keep selected ids in an array on context. But id doesnt work too.
There are a few steps to solving this problem, which you have not shown in your code examples.
you dont need to worry about binding a checked value on the checkbox.. it can manage its own internal state, and you can take advantage of it when selecting an item... a native <input> should be fine
<input type="checkbox">
You will need an action (preferably a closure action) that handles what to do when a record is selected
onchange={{action (action "valueHasChanged" item) value="target.checked"}}
You will need an array to store the "selected items"
this.selectedItems = [];
I put together a twiddle as one example of how these pieces fit together.
(This answer should be valid with ember version 1.13.0 and up)
I'am guessing your model is an array of rows.
So try adding a chked (boolean) property to the model structure so you now have one for each row and bind it to the respective checkbox.
I finished with such technic:
components/action-based-checkbox.hbs
{{#if checked}}
<input type="checkbox" {{action changed}} checked="checked" />
{{else}}
<input type="checkbox" {{action changed}} />
{{/if}}
In context we have array with selected items, for instance "selectedItems"
In context we have an action, that manages array
//2 and 3 steps example
actions:{
marked(id){
this.selectedItems.push(id);
var uniq = this.selectedItems.uniq();
this.set('selectedItems', uniq);
},
selectedItems:[],
4.next I put the component to my cell
{{inputs/action-based-checkbox changed=(action marked record.id) checked=(in-arr record.id selectedItems)}}
in-arr my "in_array?" helper, ember 2.3
I want to display a list of things and let users edit them.
The list is generated using ng-repeat. At first when it was displayed, it should be in the form of pure texts. But when the user pushed the corresponding edit button, it should be changed into an input textfield, with the contents unchanged. When the user submits the form, the data is saved and the input should be changed back to pure texts.
Is this compatible with the Angular way of thinking? If so, how do I realize it? If not, what is the correct way to realize the idea in AngularJS?
Something like this would probably work:
<ul>
<li ng-repeat='item in items'>
<span ng-hide='item.editing'>item.value</span>
<input type='text' ng-show='item.editing' ng-model='item.value' />
<button ng-click='item.editing = !item.editing'>Edit</button>
</li>
</ul>
Then in your submit action set item.editing = false for every item in items
other way or way that i prefer with angular js is to keep a track of current item on scope, this works better if you the fields being edited are in large number
$scope.currentitem;
setting current item equal to the item tha's being edited
<button ng-click='currentitem = item'>Edit</button>
Now you can have an form filled in like
<input type='text' ng-model='currentitem.value' />
I have a character which can contain multiple skills.
Skills are available from an injected service.
What I basically want is this:
<div ng-repeat="skill in character.getSkills()">
<select ng-model="skill" ng-options="select as s.toString() for s in getAllSkills()"></select>
<button ng-click="character.removeSkill(skill)" >Remove Skill</button>
</div>
With this code, the select box doesn't work as I would expect it. Skills are not set in the character, and selections are not kept in the drop down.
Am I missing something?
Thanks in advance,
roemer
After all, I'm referencing the skill in the character.skills array by the $index property in the child scope:
<select ng-model="character.skills[$index]" ng-options="sk as sk.toString() for sk in getAllSkills()"></select>