Get / Set entity when dealing with relation attribute - angularjs

I'm working in a Wakanda environnement with the angular-wakanda connector.
Assume this model : Employee(firstName,lastName,company) and Company(name)
In the employee form, I have a select input that is filled with companies names (which is a entity collection).
I have set a ng-model="selectedCompany" in the select
When I select one company and perform a save, the value I get represent the value I have pass in the value of my option (ID or name).
When I assign the value to a new entity using the $create() method, I don't know which way to set the entity to the relation attribute. I assume that I have to give an entity. The thing is that I already have the entitycollection with all the entities. So I don't see the reason why should I query again the server just to assign somthing that I have already.
So the thing is that we should have a method like $find or $getById that will not do a request on the server but get the entity that is already loaded in the entityCollection. For now I use my own method that do a simple loop over my array. (I can share the code if anybody need it)
Am I missing a way to do that?

Assuming your selectedCompany variable contains an entity (of type Company), you only have to pass this variable on the $create() call with the property name like this:
var newEmployee = ds.Employee.$create({
firstName: 'foo',
lastName: 'bar',
company: $scope.selectedCompany
});
If selectedCompany contains only company name or ID, it's on you to have an array to map the companies with their name or ID. Something like that:
//When retrieving collection
var companyMap = [];
companies.forEach(function (company) {
companyMap[company.ID] = company;
}
//When you want your company with its ID
var company = companyMap[$scope.selectedCompany];
But the simplest way is the first, with your <select> directly iterating through entity collection, so that you can deal with entities.
Edit: Retrieving object with ng-option
To get the object on which you iterate on your select, you can use ng-option like this:
<select
ng-model="selectedCompany"
ng-change="companyChanged()"
ng-options="c.name for c in companies"
>
</select>
On the controller
$scope.selectedCompany = null;
$scope.companyChanged = function () {
if ($scope.selectedCompany) {
//selectedCompany is your company entity
//you can manipulate it like any other entity
$scope.selectedCompany.$save(); //for example
}
};

I think that your real problem is that you iterate on name/ID of each entity of company Collection.
This is the bad way to iterate on collections :
<select ng-model="selectedCompany" ng-options="company.nom as company.nom for i in collenctionOfCompanies">
<option value=""></option>
</select>
In this case selected company will contain only the name of the company.
But if you change your code as this :
<select ng-model="selectedCompany" ng-options="company as company.nom for i in collenctionOfCompanies">
<option value=""></option>
</select>
Then selectedCompany will contain the entity

Related

Mapping ng-model with corresponding ng-value from json data for select

I have a select element like this
<select class="span3" ui-select2="{minimumResultsForSearch: -1}" ng-model="envelope.roofType">
<option value="">Select..</option>
<option ng-value="roof.id" ng-repeat="roof in roofList">{{roof.type}}</option>
</select>
So basically i'm sending the id corresponding to roofType in my post call.Now in my get call i get the same id back.I'm doing this in my controller.
$scope.envelope = success.records;
Now in my view since ng-model corresponds to envelope object,envelope.roofType is showing the id instead of actual type.
My question is,is there any way to map these id to actual text that should be displayed?
If you want to get the element that corresponds to that id, you can do it with a simple find function:
$scope.envelope = roofList.find(function(element) {
return element.id == success.records ;
});
This will return the element of the array that corresponds to the id, I'm supposing success.records is the id that you wanna map.

Where to store an array of object, which is part of an another object in angular2?

I have a companies' object. In this object, I have some other object..
object{
country {
country_code: string;
country_name: string
},
yearlyIncome {
id: number;
amount: string;
},
...
}
In my project you can create new companies, or edit an existing one. I use this objects there in dropdown lists. So you not writing this datas in to a textfield, you select countries in the dropdown list, select yearly income category, like 0-1000 USD, 1000-5000 USD, ... .
So this objects have default datas, but I don't know where to store this datas. I don't thinks this is good idea to store this datas in a database, bacause, this datas will not change. So I want to write the dafault datas to the code. But where to? Create a model and a service for each object? But if I do, there will be a lot of models and services. Store it in the company service? But then the company service will be very long.
How should I solve this problem?
Store the default values in a database and use the service to get the values :
ngOnInit(){
this.countries$ = this.companyService.getDefaultCountries();
this.incomeRanges$ = this.companyService.getDefaultIncomeRanges();
}
Make sure that your backend caches these values.
If you are using Express.js, you could use apicache
Then in your template, you can use this to initialize your dropdowns
<select>
<option *ngFor="let country of countries$ | async" value="country">{{country.name}}</option>
</select>

getting selected value for select list in angular from a $firebaseArray()

I have a simple select list that is based on a $firebaseArray(). I dont have a problem getting the values into the drop. Just the selected value.
<select class="form-control" ng-model="vm.selectedRole"
ng-options="role.name for role in vm.allRoles">
</select>
The $firebaseArray looks like this
In my controller the function that initializes the form with the select is
Get.getParentUrl('roles').$loaded()
.then(function (data) {
vm.allRoles = Get.getParentUrl('roles');
vm.selectedRole = entity.role.name;
})
And this populates the select but it does not set the selected value for it on vm.selectedRole. Note that entity is the value that is being passed , so if i write a
console.log(entity.role.name);
The returned value is the selected value that is being passed. So if the user selects a user with a role "Supervisor" and i write a console.log(vm.selectedRole) inside the .then(function(data){ the value returned is "Supervisor"
However the html displays a "?"
I got it working by adding the vm.selectedRole like so
vm.selectedRole = { name: entity.role.name };
Which works i guess. Syntax seems a bit crappy though
https://docs.angularjs.org/api/ng/directive/ngOptions

AngularJS adding 2 properties to associated collections

1. I have a Truck class that has a collection called AxleTypes with the following markup:
public class AxleType : Entity
{
public string Description { get; set; }
public string Type { get; set; }
}
2. My angular form includes the following (to keep this as short as possible I omitted the form's other axle types, and I am using $parent, as this is a template and on main form thru ng-include):
<label for="frontAxles">Front Axle: </label>
<input ng-model="$parent.frontAxleType" type="hidden" value="Front">
<select ng-model="$parent.selectedFrontAxle" ng-options="axleType.Description for axleType in axleTypes">
<option value="" selected>Select Axle Type ..</option>
</select>
3. The main form inserts a new truck via the truck controller, so in the truck controller:
a. I instantiate an instance of the AxleTypes collection so the form is populates the select w/axle types.
b. I instantiate an instance of AxleType to pass the selected data from the form.
c. I pass the respective ng-models on the form to the AxleType variable.
d. I add that AxleType variable to the Truck's AxleTypes collection.
a: if ($scope.axleTypes == undefined || !($scope.axleTypes.length > 0))
{ $scope.axleTypes = API.GetAxleTypes(); }
b: $scope.axleType = {};
c: var frontAxle = $scope.axleType;
frontAxle.Description = $scope.selectedFrontAxle;
frontAxle.Type = $scope.frontAxleType;
d: newTruck.AxleTypes = [
angular.copy(frontAxle)
];
When debugging this is the end result:
To keep this as short as possible I did not illustrate the 2nd axle type select above. But as you can see, the server is picking up 2 axle types however, both properties for each [Type & Description] are null.
Does anyone have any suggestions?
In console.log both values are "undefined".
An interesting observation:
When I hard code the values in the TruckCtrl, everything works fine:
frontAxle.Description = 'Some Front Value';
frontAxle.Type = 'Front';
rearAxle.Description = 'Some Rear Value';
rearAxle.Type = 'Rear';
newTruck.AxleTypes = [
angular.copy(frontAxle),
angular.copy(rearAxle)
];
This would lead someone to think the problem lies with the ng-model on the axle template. However, when I only had one property, ie Description, and not Type in the server class, AxleType, and merely added the select's description via:
newTruck.AxleTypes = [
angular.copy($scope.selectedFrontAxle),
angular.copy($scope.selectedRearAxle)
];
The values passed. Very confusing.
SOLVED !!!
There is alot I would like to say to the 40 some odd eyeballs who perused this problem with no input, and Stewie, well, we know what Stewie is. But I won't. Instead I offer help to those who have this same problem.
OK, on to the solution.
Problem #1: Angular does not accept default values in html inputs.
I was confused why I had an input like so:
<input ng-model="$parent.selectedRearType" type="hidden" value="Front">
and yet angular said it had no value.
SOLUTION TO PROBLEM #1:
You need to initialize the following in your controller:
$scope.selectedFrontType = 'Front';
$scope.selectedRearType = 'Rear';
Problem #2: How do you pass values of multiple properties in a collection?
Despite how real-world this scenario is, it is unsettling that there is ZERO documentation on the matter.
SOLUTION TO PROBLEM #2:
In my html I had this select statement:
<select ng-model="$parent.selectedFrontAxle" ng-options="axleType.Description for axleType in axleTypes">
Where I erred was thinking this ng-model was STRICTLY the Description property of the class AxleType (see my class model above). That was a huge mistake, it was not. That ng-model was not the Description property of the class but actually the entire class itself. So when examining that select's ng-model, realize it is the AxleType class in its entirety, even if only Description property is provided. So what ng-model was giving me was this as a return value in my controller after the user made a selection:
AxleType class => Description = "Whatever the person selected", Type=""
With that being the case, I needed to fill in the blanks angular did not have, namely in this scenario, the Type property.
Here's the whole solution:
// beginning of controller when it initializes
$scope.selectedFrontType = 'Front';
$scope.selectedRearType = 'Rear';
// $scope.axleType = {}; -> NOT NEEDED
// in the save method
// axles
var frontAxle = $scope.selectedFrontAxle;
frontAxle.Type = $scope.selectedFrontType;
var rearAxle = $scope.selectedRearAxle;
rearAxle.Type = $scope.selectedRearType;
newTruck.AxleTypes = [
angular.copy(frontAxle),
angular.copy(rearAxle)
];
I hope I have helped someone!

AppEngine Datastore get entities that have ALL items in list property

I want to implement some kind of tagging functionality to my app. I want to do something like...
class Item(db.Model):
name = db.StringProperty()
tags = db.ListProperty(str)
Suppose I get a search that have 2 or more tags. Eg. "restaurant" and "mexican".
Now, I want to get Items that have ALL, in this case 2, given tags.
How do I do that? Or is there a better way to implement what I want?
I believe you want tags to be stored as 'db.ListProperty(db.Category)' and then query them with something like:
return db.Query(Item)\
.filter('tags = ', expected_tag1)\
.filter('tags = ', expected_tag2)\
.order('name')\
.fetch(256)
(Unfortunately I can't find any good documentation for the db.Category type. So I cannot definitively say this is the right way to go.) Also note, that in order to create a db.Category you need to use:
new_item.tags.append(db.Category(unicode(new_tag_text)))
use db.ListProperty(db.Key) instead,which stores a list of entity's keys.
models:
class Profile(db.Model):
data_list=db.ListProperty(db.Key)
class Data(db.Model):
name=db.StringProperty()
views:
prof=Profile()
data=Data.gql("")#The Data entities you want to fetch
for data in data:
prof.data_list.append(data)
/// Here data_list stores the keys of Data entity
Data.get(prof.data_list) will get all the Data entities whose key are in the data_list attribute

Resources