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/
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
I've done Dan Abramov's intro series on EggHead, and am working on a real world app. The domain is complex, so I'll run with a classic "blogs" example.
Let's say, we have an "index / list" page, where all we need to show are the blog post's title and blurb. So we have an API endpoint that returns that, and we store it in our state tree under blogs.byId.
Then, when you click through on a blog post, we actually need a bunch more info - e.g. the full blog post, and also tags and categories. Let's call this "blogs with metadata".
Stretching the example, there might be another completely separate page where I want to display a list of blog posts with the most recent 3 comments. Let's call this "blogs with comments".
My question is, how should my state tree treat these separate examples where I'm storing the same "thing" but in different "formats"? My initial hunch would be to treat them as completely separate data types, so my state tree would have eg: blogs.byId, blogsWithMetadata.byId and blogsWithComments.byId.
And then, even if every single blog post is cached in the blogs.byId section, the minute we need to view a blog post, the app completely ignores that warm blogs.byId cache, and looks only at blogsWithMetadata.byId - so we'd essentially be building up 3 separate caches of blog data, each with different amounts of info, and treating it as though they are as unrelated to each other as "blogs" and a completely unrelated table like "widgets" would be.
Is this correct? Or is there a better way?
The app currently rams them all under the same node, without distinction based on "format" and it's causing a world of pain.
There are probably many ways you could choose to do this. One of it is to use normalizr to structure your data.
Your blog post could have a data structure returned by the API like this:
{
"id": "123",
"author": {
"id": "1",
"name": "Paul"
},
"title": "My awesome blog post",
"comments": [{
"id": "324",
"commenter": {
"id": "2",
"name": "Nicole"
}
}],
"tags": [{
"id": "1",
"value": "awesome"
}, {
"id": "2",
"value": "journal"
}],
"categories": [{
"id": "1",
"value": "personal"
}, {
"id": "2",
"value": "life"
}]
}
which after normalizing, will look something like this:
{
entities: {
"post": {
"123": {
id: "123",
author: "1",
title: "My awesome blog post",
comments: ["324"],
tags: ["1", "2"],
categories: ["1", "2"],
}
},
"users": {
"1": { "id": "1", "name": "Paul" },
"2": { "id": "2", "name": "Nicole" }
},
"comments": {
"324": { id: "324", "commenter": "2" }
}
"tags": {
"1": { id: "1", "value": "awesome" },
"2": { id: "2", "value": "journal" },
}
"categories": {
"1": { id: "1", "value": "personal" },
"2": { id: "2", "value": "life" },
}
}
}
Subsequently, you could have a state for each page if you needed to:
{
entities: {...},
ui: {
blogs: {
posts: [1, 2],
hasComments: false,
// Displaying the blogs with or without comments
// could simply just be a boolean flag in state.
},
}
}
using reselect, you then create the selectors to pass the posts you want as props to the page Components.
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 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
};
I am using the Rally WSAPI 2.0p5 with and the JSON return
I am looking to get fields from multiple tables in a single response. Is this possible? For example I am trying to get the User Story and also get the Iteration.State in the same data response. I know it is possible to do client side and if that is the only way. Can someone provide and example how I handle the async response to build the table (array).
Simply add State to the list of attributes included in your fetch. Rally's WSAPI will populate the value for sub objects even if the main type being queried does not have that field.
launch: function() {
var userStories = Ext.create('Rally.data.WsapiDataStore', {
model: 'HierarchicalRequirement',
fetch: ['Iteration', 'State'],
autoLoad: true,
filters: [
{
property: 'Iteration.State',
value: 'Accepted'
}
],
limit: 10000,
listeners: { load: this._onDataLoaded, scope: this }
});
}
As a follow up for my original question. I recently came across the alpha release of the Batch Query WSAPI in Rally's WSAPI documentation. I would suggest the usage of the Batch Query to retrieve multiple Object Models in a single response.
As an example to get User Stories and get the Iteration Status in a single query.
{
"stories" : "/HierarchicalRequirement?fetch=Name,Iteration,State&query=(Iteration.State = Accepted)"
}
The result is something that is more usable and doesn't require multiple queries to the server. i.e.
"Results": [{
"_rallyAPIMajor": "1",
"_rallyAPIMinor": "40",
"_ref": "https://rally1.rallydev.com/slm/webservice/x/hierarchicalrequirement/xxxxxxxx.js",
"_objectVersion": "17",
"_refObjectName": "<user role> I would like <feature> for <benifit>",
"Name": "As a <user role> I would like <feature> for <benifit>",
"Iteration": {
"_rallyAPIMajor": "1",
"_rallyAPIMinor": "40",
"_ref": "https://rally1.rallydev.com/slm/webservice/x/iteration/xxxxxxxx.js",
"_objectVersion": "4",
"_refObjectName": "Sprint #",
"Name": "Sprint #",
"State": "Accepted",
"_type": "Iteration"
},
"Project": {
"_rallyAPIMajor": "1",
"_rallyAPIMinor": "40",
"_ref": "https://rally1.rallydev.com/slm/webservice/x/project/xxxxxxxx.js",
"_refObjectName": "Name",
"_type": "Project"
},
"_type": "HierarchicalRequirement"
},
....
]
For more information and a few resources:
https://rally1.rallydev.com/slm/doc/webservice/index.jsp?version=1.40
https://rally1.rallydev.com/slm/doc/webservice/batch.jsp
https://rally1.rallydev.com/slm/doc/webservice/BatchScratchPad.jsp