Angular ng-options behaves odd - javascript

I have this typahead with angular strap:
<div class="form-group" ng-class="newGroupForm.placeReference.$invalid ? 'has-error' : ''">
<label for="placeReference" class="col-lg-2 control-label">Group Location</label>
<div class="col-lg-10">
<input type="text" name="placeReference"
ng-model="newGroup.reference"
ng-options="place.reference as place.name
for place in getPlaces($viewValue)"
bs-typeahead min-length="0" required >
</div>
</div>
getPlaces returns array of objects which looks like this:
{
reference: "ccj32213SIJD",
name: "some name",
}
When I am typing I am getting correct results, but when I select the wonted option the value that I see in my input is the reference (instead of the name).
Can any one point out my mistake?
Here is the controller code:
$scope.getPlaces = function(viewValue) {
var input = viewValue || $scope.currentPlace;
return googleService.placesAutocomplete(input).then(
function(places) {
return places;
}
);
};

If ng-options here behaves exactly like <select ng-options> (sorry, I'm not familiar with bs-typeahead directive), then you should change it to:
<input ...
ng-model="selectedPlace"
ng-options="place as place.name for place in getPlaces($viewValue)">
Then you can use get the name elsewhere:
<div>{{selectedPlace.name}}</div>
It's probably best to get the actual place object {name: "..", reference: "..."}, but if you just need the name, then you could do this:
<input ...
ng-model="selectedPlaceName"
ng-options="place.name as place.name for place in getPlaces($viewValue)">

Related

how to use a variable in type of input

in my form i have the label and input value who come from json like this
"attribut1":{
"name":"attrib1",
"type":"text"
},
"attribut2":{
"name":"attrib2",
"type":"number"
}
So for label i just put value.name it gaves me the name, but when i put inside the type of input value.type it doesn't work like
<label for="key">{{value.name}}</label>
<input type="value.type" class="form-control form-control-rounded" id="key" placeholder="">
I dont know how to set the type as variable, I need some help please
Use double curly brace notation to set the attribute.
var myApp = angular.module('DemoApp', []);
myApp.controller('DemoCtrl', function() {
this.inputs = {
"attribut1": {
"name": "attrib1",
"type": "text"
},
"attribut2": {
"name": "attrib2",
"type": "number"
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="DemoApp" ng-controller="DemoCtrl as ctrl">
<ng-container ng-repeat="a in ctrl.inputs">
<label>{{a.name}}</label>
<input type="{{a.type}}">
</ng-container>
</div>
Using JQuery you can set the value of input field like:
$("#inputFieldID").val(value.name);
$("#inputFieldID").clone().attr('type',value.type).insertAfter("#inputFieldID").prev().remove();
I think you can only do it with Javascript, so just use something like this to get the variable inside.
<label id="key_label" for="key">{{value.name}}</label>
<script>
document.getElementById("key_label").innerHTML = myObj.name;
</script>

Binding ng model by key of loop issue

I'm trying to bind value to ng-model="" directive because I'm displaying elements with it in loop.
I tried like this
<div class="form-group">
<div data-ng-repeat="(key, n) in langInput.values">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 u-no-padding">
<label class="sell__label" for="auction_name_account_{{n.selected }}">Główna nazwa Twojej aukcji ({{n.selected }}):</label>
<div class="pst-relative">
<input type="text"
id="auction_name_account_{{n.selected }}"
class="form-control"
name="auction_name_account"
data-ng-model="inputs.auction_name_account[key]"
data-ng-minlength="10"
data-ng-maxlength="60"
required />
<span class="sell__input-text sell__input-text--big-input" data-ng-show="sellItem.auction_name_account.$error.required">Wymagane!</span>
<span class="sell__input-text sell__input-text--big-input" data-ng-show="sellItem.auction_name_account.$error.minlength">Za krótkie!</span>
<span class="sell__input-text sell__input-text--big-input" data-ng-show="sellItem.auction_name_account.$error.maxlength">Za długie!</span>
</div>
</div>
</div>
I need to have unique models to firstly create working validation (spans below) and to gather and send data to rest api later on.
This [key] somehow doesn't print as key of object which is number but as normal string as I see in console.
Data of langInput is
$scope.langInput = {
values: [
{
id: 1,
selected: "pl"
},
{
id: 2,
selected: "eng"
}
],
And I would like to have ng-model="inputs.auction_name_account[1]" where 1 is binded value or something similiar. Also above array of objects changes.
auction_name_account is going to be an Object when it's produced.
This means all property accessors must be a string and that properties which aren't a string, will be typecasted into one. This is why, while key is an integer, it will be casted as a string upon usage.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors#Property_names

creating property dynamically in ng-model

<div class="form-group" data-ng-repeat="choice in choices">
<input type="text" ng-model="user.subjectname[$index]"
name="subject" ng-required="true" placeholder="Enter a subject name">
</div>
As I am creating this input field dynamically using ng-repeat, if I used ng-model=user.subjectname, the input text for some reason was same in all the fields, I searched over the internet and found ng-model="user.subjectname[$index]" being used and it worked.
However, i am not able to understand
what it exactly means. ?
2.If it's array or an object. ?
It shows up as object in console. ?
If it's object, why does it have an index?
Also, as we can iterate over object vals using this format:
ng-repeat="(key,val) in user.subjectname"{{val}}
Why did it not work?
neither did ng-repeat="subject in user.subjectname"{{subject}}
Can I please get directions as I am very confused about it at the moment.
It is an array. When you do :
var test = []; console.info(typeof test);// You would get object as arraysa re also object in Javascript.
Here you are passing $index of choice in choices to subjectname array. Which is fine. After populating subjectname with some of the data, you can use ng-repeat like
ng-repeat = "subject in user.subjectname"
Also initialize user.subjectname = []; in controller
<form class="idea item">
<div ng-repeat="(key, value) in items[0]" >
<label>{{key}}</label>
<input type="range" ng-model="items[0][key]" min="0" max="15"/>
</div>
<input type="submit" ng-click="save()" />
<pre>{{items | json}}</pre>
var app = angular.module('my-app', [], function () {
})
app.controller('AppController', function ($scope) {
$scope.items = [{"red": 14, "green": 12, "orange": 1, "yellow": 11, "blue": 9}];
})

Populating dropdownlist using knockout observable array

I am trying to bind 2 drop down lists to knockout observable arrays.The condition is that the first drop down list has to get populated first.The second drop down list is dependent on the first drop down list.Hence I am subscribing to the first drop down list to populate the second drop down list.
To try and achieve this,I have written the following code
HTML is
<div class="form-group">
<label class="col-sm-2 control-label labelfont">Certification:</label>
<div class="col-sm-6">
<select class="form-control" id="certification" name="certification" data-bind="value: certification, options: certificationArray, optionsText: 'Certification', optionsValue: 'CertificationID', optionsCaption: 'Select a Certification'">
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label labelfont">Specialization:</label>
<div class="col-sm-6">
<select class="form-control" id="specialization" name="specialization" data-bind="value: specialization, options: specializationArray,optionsText:'Specialization',optionsValue:'SpecializationId', optionsCaption: 'Select a Specialization'">
</select>
</div>
</div>
The view model is
self.specializationArray = ko.observableArray([]);
self.certificationArray = ko.observableArray([getCertifications()]);
self.certification = ko.observable("");
self.specialization = ko.observable("");
self.certification.subscribe(function () {
self.specializationArray([]);
getSpecializations();
}
});
The functions to get the respective certifications and speciaizations are
var getCertifications = function () {
$.getJSON("/Provider/GetCertifications", function (data) {
return data;
});
});
};
var getSpecializations = function () {
$.getJSON("/Provider/GetSpecializations/", { certificationID: $("#certification").val() }, function (data) {
self.specializationArray(data)
})
}
The JSON response looks like this
and the JSON looks like this
Could someone please guide me in the right direction,I am completely new to knockout and JSON.I am at my wit's end here.So,any help would be greatly appreciated.Thanks in advance.
In KnockOut, the values of the arrays are separate from the options the dropdowns get. You wouldn't change the observableArray, but the value observable itself. Better, though, would be to use a ko.computed field to hold the value of the 2nd dropdown.
I don't really understand why you think your dropdowns must get bound in a certain order, though. I'm not exactly sure how the Certifications and Specializations have to do with each other from your question. You aren't really doing anything in self.certification.subscribe(), like there was any dependency when filling in the Specialization. The JSON you supplied in the Certifications also does not have any related Specialization foreign key. But if your JSON for Certification looked like this:
[{"CertificationID": 1, "Certification": "M.B.B.S.", "SpecializationID": "7"},{"CertificationID": 2, "Certification": "M.D.", "SpecializationID": "3"}, ...]
while the JSON for Specialization looked like this...
[{"SpecializationID": 1, "Specialization": "Cardiology"},
{"SpecializationID": 2, "Specialization": "Dentistry"},
{"SpecializationID": 3, "Specialization": "General Practioner"}, ...
{"SpecializationID": 7, "Specialization": "Surgery"}
]
I believe something like this should work:
self.specialization = ko.computed(function() {
return ko.utils.arrayFirst(getCertifications(), function(certs) {
return certs.ID == self.SpecializationID();
}).SpecializationID;
});
But since I don't see where you have any dependencies, here, why not just fill them in, directly:
self.certificationArray = ko.observableArray(getCertifications());
self.specializationArray = ko.observableArray(getSpecializations());
self.certification = ko.observable(vm.certification);
self.specialization = ko.observable(vm.specialization);
And you set those values using the viewmodel returned from the dataset, which should be ID fields in your database table (CertificationID, SpecializationID).

Rendering all form values after service call using AngularJS

I have an Angular article form that I'm populating using a service call. The problem is that, in order to get validation and data binding to work, I have to use $setViewValue and $render on each form input. What I'd like to do is simply set the data model for the form and then render the entire form somehow.
Here is a sample of what I have that works:
var _promise = articleService.getArticle($scope.params.articleId);
_promise.then(
function(data) {
$scope.articleForm.title.$setViewValue(data.item.title);
$scope.articleForm.title.$render();
$scope.articleForm.bodytext.$setViewValue(data.item.body);
$scope.articleForm.bodytext.$render();
$scope.articleForm.keywords.$setViewValue(data.item.keywords);
$scope.articleForm.keywords.$render();
},
function() {
$scope.setMessage('There was a network error. Try again later.', 'error');
}
);
The code below accomplishes the same result visually (just doesn't render bindings, like updating fields to dirty in validation):
var _promise = articleService.getArticle($scope.params.articleId);
_promise.then(
function(data) {
// $scope.article breakdown: article.title, article.body, article.keywords
$scope.article = angular.copy(data.item);
// some sort of complete form render???
},
function() {
$scope.setMessage('There was a network error. Try again later.', 'error');
}
);
HTML:
<form name="articleForm" novalidate role="form">
<!-- TITLE -->
<div class="form-group" ng-class="{ 'has-error' : (articleForm.title.$invalid && !articleForm.title.$pristine) || (submitted && articleForm.title.$pristine) }">
<label>Title</label>
<input type="text" name="title" ng-model="article.title" ng-minlength="3" required>
<p ng-show="(articleForm.title.$error.required && !articleForm.title.$pristine) || (submitted && articleForm.title.$pristine)" class="help-block">A title is required.</p>
<p ng-show="articleForm.title.$error.minlength" class="help-block">Title is too short.</p>
</div>
<!-- BODY -->
<div class="form-group" ng-class="{ 'has-error' : articleForm.bodytext.$invalid && !articleForm.bodytext.$pristine }">
<label>Article Body</label>
<div text-angular ng-model="article.body" ng-change="updateBody()" id="bodytext" name="bodytext"></div>
</div>
<!-- KEYWORDS -->
<div class="form-group" ng-class="{ 'has-error' : (articleForm.keywords.$invalid && !articleForm.keywords.$pristine) || (submitted && articleForm.keywords.$pristine) }">
<label>Keywords</label>
<input type="text" name="keywords" ng-model="article.keywords" ng-minlength="3" ng-maxlength="150" required>
<p ng-show="(articleForm.keywords.$error.required && !articleForm.keywords.$pristine) || (submitted && articleForm.keywords.$pristine)" class="help-block">At least one keyword is required.</p>
<p ng-show="articleForm.keywords.$error.minlength" class="help-block">Keywords is too short.</p>
<p ng-show="articleForm.keywords.$error.maxlength" class="help-block">Keywords is too long.</p>
</div>
</form>
I feel like there should a simple solution to this, since it's a common scenario, but I've searched high and low without a clear answer. Maybe I'm just approaching this the wrong way?
Well, I found a solution that works, but I don't think it's a better solution than just setting all the form fields individually. I'll post it here though, in case it helps anyone else in some way.
// set all the values via the angular model
$scope.article = angular.copy(data.item);
// without a timeout all the fields will still be unset (being asynchronous)
$timeout(function() {
// loop through all the form values
angular.forEach($scope.articleForm, function(value, key){
if(typeof value === 'object' && key !== '$error'){
// reset the view value and render, to process the updates on the form
$scope.articleForm[key].$setViewValue($scope.articleForm[key].$viewValue);
$scope.articleForm[key].$render();
}
});
});

Categories

Resources