I'm trying to create a form with Angular JS that lets you edit a venue (address, city etc).
The backend runs Django and is available through a REST API (Django Rest Framework) which I'm talking to via Restangular services. This all works fine.
For most form elements, things are pretty standard. I have a venue object and just populate the items with, for example:
<input type="text" ng-model="venue.street">
However, every venue object has a category which, on the backend, is a foreign key to a category object, so in Django this would be:
category = models.ForeignKey(Category)
Now, when getting a venue through the REST API, the category is just referenced by the pk/id of the category object. So, for example, this would be:
{
"id": 14,
"name": "test place",
"slug": "test-place",
"country": "Ireland",
"city": "Dublin",
[...etc...]
"category": 1
},
And a separate REST endpoint, gets me the categories:
[
{
"id": 1,
"name": "Rock"
},
{
"id": 2,
"name": "Classic"
},
{
"id": 3,
"name": "Jazz"
}
]
My problem is that when editing the venue, I would like the drop down menu for categories to show categories by name but just feed the category ID to the backend, as well as pre-select the venue's current category when first shown.
I'm new to Angular but, as far as I can understand, Angular populates a select directive with references to the object itself, not something simple like an ID.
At the moment I have this:
<select ng-model="venue.category" ng-options="category.name for category in categories track by category.id"></select>
Obviously, this doesn't work as, even though venue.category is just a number, and category.id also, they are not the same object.
I'm probably missing an obvious solution here but would appreciate any pointers.
Thanks!
Track by is for when you want two different objects to be equal in regards to the select box. This isn't the case. You just want the model to be the id itself. Angular supports this like so.
http://jsfiddle.net/XLpFN/
Example:
<select ng-model="venue.category" ng-options="category.id as category.name for category in categories"></select>
$scope.categories = [
{"id": 1, "name": "Rock"},
{"id": 2, "name": "Classic"},
{"id": 3, "name": "Jazz"}
];
$scope.venue = {
"id": 14,
"name": "test place",
"slug": "test-place",
"country": "Ireland",
"city": "Dublin",
"category": 2
};
Related
I am new to AngularJs. I am having problem in appending options to select boxes created by javascript. Following is my code.
var inputElements = $('<div><label style="float:left;">' + i + '</label><select ng-model="object" class="form-control sel" style="width:300px; float:right; margin-right:75px;"> <option>select</option></select></div></br></br>');
var temp = $compile(inputElements)($scope);
$('#projOrder').append(temp);
$scope.object = object;
//for(var opt=0; opt<selOptLabels.length; opt++) {
$('.sel').append('<option ng-repeat="obj in object" value="'+
{{obj.value}}+'">'+{{obj.value}}+'</option>');
I am getting this error:- SyntaxError: invalid property id
Hi, I am posting json example. This is just a small part of json in my case.
"ProjectOrder": {
"Connect direct required": {
"value": "N",
"id": "STR_15523_62"
},
"Cores": {
"value": ".5",
"id": "NUM_15523_50"
},
"Permanent data in GB": {
"value": "100",
"id": "NUM_15523_56"
},
"Description": {
"value": "AZBNL azbngb",
"id": "STR_15523_2"
},
"Order Id": {
"value": "15523",
"id": "INT_15523_96"
},
"Project cost center": {
"value": "N",
"id": "STR_15523_66"
},
"Project debitor": {
"value": "N",
"id": "STR_15523_64"
},
"Project OE": {
"value": "N",
"id": "STR_15523_57"
},
"Project SITE": {
"value": "N",
"id": "STR_15523_59"
},
"Project Status": {
"value": "RFC",
"id": "STR_15523_54",
"dropdown": [
{
"value": "IW",
"label": "In Work"
},
{
"value": "RFC",
"label": "Ready for Creation"
},
{
"value": "CR",
"label": "Created"
},
{
"value": "FC",
"label": "Failed"
}
]
},
"Project Type (paas, miner)": {
"value": "paas",
"id": "STR_15523_37",
"dropdown": [
{
"value": "paas",
"label": "PaaS Project"
},
{
"value": "miner",
"label": "Miner Project"
}
]
},
"WORK data in GB": {
"value": "100",
"id": "NUM_15523_55"
}
}
Now I have to create input fields and dropdown menus(if there is a dropdown menu) with json data
You really should not be hand-constructing HTML like that. It's best if you use a template and let the template engine handle the heavy lifting.
I also noticed that you're using object as the ng-model. Instead you should have a separate variable which will hold the selected value.
Here's a better way of doing this--in an .html file:
<div ng-repeat="object in listOfObjects"
<label style="float: left">{{ $index }}</label>
<select ng-model="selectedValues[$index]" class="form-control sel"
style="width:300px; float:right; margin-right:75px;"
ng-options="obj.value for obj in object"></select>
</div>
Then in whatever controller you have set up in JavaScript:
// this will be the list of selected values
$scope.selectedValues = new Array(list.length);
// this would be the array that each `object` is part of
$scope.listOfObjects = list;
This isn't the most elegant solution, but basically what I've done is construct an array that is the same length as the list of objects. Angular templates have a special variable $index when you're in an ng-repeat which tracks the current index of the array you're looping through.
So when a user changes the selected value of the 3rd select box (index 2), $scope.selectedValues[2] would be set to the selected option.
EDIT: on transforming the JSON to an array:
var list = Object.keys(json).map(function(jsonKey) {
return {
name: jsonKey,
label: json[jsonKey].label,
value: json[jsonKey].value
};
});`
So.. there are a number of reasons why that won't work. The provided code wouldn't even work because of the template brackets that you are trying to append to your html string...
$('.sel').append('<option ng-repeat="obj in object" value="' +{{obj.value}}+'">'+{{obj.value}}+'</option>');
Is there a reason that you are trying build your markup in js?
It's also advised not to use jquery inside angular controllers. If you have jquery loaded the jQuery object is available through angular.element, otherwise angular uses jQuery light.
Rather than enumerate on the other issues here, I put together this basic example of how a select works in Angular
https://codepen.io/parallaxisjones/pen/BRKebV
Also, you should consult the angular documentation before posting questions to stack overflow. The docs provide a pretty clear example of how to use ng-repeat in a select. https://docs.angularjs.org/api/ng/directive/select
EDIT: I updated my codepen with an example of fetching JSON data with an HTTP GET request
EDIT: updated codepen with provided data example, iterating over object with (key, value) in json syntax in ng-repeat
{Module_JSON} allow you to parse json files in Business Catalyst, however, there is NO documentation, or functionality to utilize the data using liquid. I tried talking to support, but they said that my questions were out of the support boundaries.
Here is what I would like to do: I would like to call specific items within an array via Json.
{
"description": "List of a collection of Doughnuts",
"doughnuts": [
{
"id": "5001",
"type": "Plain",
"price": 0
},
{
"id": "5002",
"type": "Glazed",
"price": 1
},
{
"id": "5005",
"type": "Sugar",
"price": 1
},
{
"id": "5007",
"type": "Powdered Sugar",
"price": 1.25
},
{
"id": "5006",
"type": "Chocolate with Sprinkles",
"price": 1.5
},
{
"id": "5003",
"type": "Chocolate",
"price": 2
},
{
"id": "5004",
"type": "Maple Syrup",
"price": 2.25
}
]
}
To parse the JSON you have to do this:
{module_json,json="/mrbean.json" template="/module_json/template.tpl"}
Let's say I would like to parse the plain donut, I would try and put the parameter right in the callback function like this:
{module_json,json="/mrbean.json" type="plain" template="/module_json/template.tpl"}
Nothing happens. Does anyone know how I can do this? Otherwise, I don't see why the Module_Json tag should be used. Should I just use Ajax instead?
There is a rather clear example here http://docs.businesscatalyst.com/Developers/liquid/render-your-own-JSON-files-using-module_json
If you need any help please post here.
Please include some more explanation in your question.
Do you have a template created?
Please post your template so I can check your syntax.
If your data rendered with json looks like this {
"description":"List of a collection of Products",
"products":[
{
"id":"SLI123",
"type":"Toy",
"price":20
},
{
"id":"SLI124",
"type":"Shirt",
"price":40
},
then you liquid rendering can be something like this
<div>{{this.description}}</div>
<ul> {%; for products in this.products %}
<li id={{product.id}} type={{product.type}}>
{%; if product.price == 20 %}
Price: Only ${{product.price}}!!!
{%; else %}
Price: ${{product.price}}
{%; endif %}
</li>
{%; endfor %}
</ul>
The tag makes no assumptions about how the json is structured. This allows it to load any valid json, but puts the onus on the caller to handle the data within.
In this case, you could use the collection parameter to assign it to a variable, like so:
{module_json,json="/mrbean.json" collection="food"}
{{ food.doughnuts[0].type }} <!-- Plain -->
(The same data is available within the named file, when using the template parameter.)
Otherwise, I don't see why the Module_Json tag should be used. Should I just use Ajax instead?
If it better suits your application to have the user make another round-trip after page load to see the data, then use ajax / fetch.
If the app should load with the data as quickly as possible, then module_json can insert the data into the first response.
I am working in a Sencha touch app, and I am finding problems to filter correctly the next scenario:
I have this API:
In this area we have different templates number related with the Id, data is saved in a store call (for example: templates):
{
"id": "0100100001",
"templates": {
"id": "0000000187", ---> customerId
"name": "TEST01",
"validFrom": "\/Date(1360710000000)\/",
"validTo": "\/Date(253402300799000)\/"
},
{
"id": "0000000188",
"name": "S_TEST_01",
"validFrom": "\/Date(1360710000000)\/",
"validTo": "\/Date(253402300799000)\/"
}
}
In other Json/store called "Survey" we save the next data,
"id": "0000104747",
"templateId": "0000000955",
"templateName": "SURVEYAPP TEST1",
"customerId": "0100100001",
Question is: How can I evaluate if the customerId has a template created in the "Surveys" store?
Thank you in advance.
I'm trying to populate a table of inputs (textboxes and select list) with JSON data retrieved from a jQuery GET request. For the example I pre-set a variable with some data rather than making a get request. The textbox inputs are correctly populating with data, but the select lists will not populate.
Here is an example of the data that knockout receives and places in the table
var returnedData = [{
"taskID": "1",
"taskName": "test task",
"taskDetails": "details",
"employee": {
"employeeID": "1",
"employeeName": "John"
}
}, {
"taskID": "2",
"taskName": "another test",
"taskDetails": "some more details",
"employee": {
"employeeID": "2",
"employeeName": "Jane"
}
}];
On the official knockout tutorials, they use a textarea (I included it in the fiddle) to show how the data is formatted as it is being posted back to the server. The pre-loaded data is in the exact same format.
Anyway, here is a fiddle with the code.
The reason that the select lists won't populate is object equality. They're bound to availableEmployees observable array with the options binding and the value binding is to Employee, but when you're setting the employee property of each task, you're setting it to a new object with the same properties and values, which is not equal in javascript. What I'd do is actually search (my example has a terrible for loop search, just to show you what I mean) for the matching employee in your list of available employees, and set the employee to that actual object, not the object coming in from the task's info. Check this out:
var returnedData = [{
"taskID": "2",
"taskName": "test task",
"taskDetails": "details",
"employee": self.availableEmployees()[1]
}, {
"taskID": "5",
"taskName": "another test",
"taskDetails": "some more details",
"employee": self.availableEmployees()[2]
}];
This is because in javascript:
var a = { foo: 1, bar: 'baz'};
var b = { foo: 1, bar: 'baz'};
console.log(a == b); // false
JSFiddle
For demo purposes, I'm writing a project tracking app. Projects have tasks, people, etc and each have associated properties like title and description.
I created a select list and expected it to be populated with the title properties of each project. Instead, it's being populated with the text of a function. I assume it's because title is an observable. But I don't know how I can ask for the value...
Here is the HTML that isn't populating correctly:
<select data-bind="options: projects,
optionsText: 'title',
optionsValue: 'id',
value: selectedList.id()">
</select>
Here is the javascript with the json included (it's injected using JSON.Net in ASP.Net MVC). The format should be the same, although I tried to sanitize it, so please excuse any missing brackets.
<script type="text/javascript">
var initialData = [
{
"id": "2150980c-1033-4b20-a58b-9e5400abb651",
"title": "project1",
"description": "project 1 description",
"persons": [
{
"id": "1f6f531c-bafa-4fe8-aac8-9e5400abb65a",
"firstname": "p1_fname"
},
{
"id": "1f6f531c-bafa-4fe8-aac8-9e5400abb65a",
"firstname": "p1_fname"
}],
"tasks": [
{
"id": "1f6f531c-bafa-4fe8-aac8-9e5400abb65a",
"title": "task1"
},
{
"id": "1f6f531c-bafa-4fe8-aac8-9e5400abb65a",
"title": "task2"
}]
},
{
"id": "54d4dc7c-0928-4c05-93a2-9e5400abb6a0",
"title": "project2",
"description": "project 2 description",
"persons": [
{
"id": "1f6f531c-bafa-4fe8-aac8-9e5400abb65a",
"firstname": "p1_fname"
},
{
"id": "1f6f531c-bafa-4fe8-aac8-9e5400abb65a",
"firstname": "p1_fname"
}],
"tasks": []
}
];
var viewModel = {
projects: ko.mapping.fromJS(initialData)
};
viewModel.selectedList = {
id: ko.observable("")
};
if(viewModel.projects().length > 0)
viewModel.selectedList.id(viewModel.projects()[0].id());
ko.applyBindings(viewModel);
</script>
EDIT:
Green was right. The code is fine. I hadn't provided enough information. I was using Knockout 1.1.1 with mapping plugin 0.5. This is what caused the problem. Knockout is currently on v1.1.2. When I upgraded to 1.1.2, it worked. Good catch green. I should have checked it in fiddle first.
Note: It doesn't look like there is currently any documentation indicating the requirement to use 1.1.2.
I don't see the problem with the code. The fiddle shows the selection is correctly populated with project title: http://jsfiddle.net/greenlaw110/Tkqqb/3/