I have two dropdowns where I am passing two arrays from my angularjs file. One drop down has the names and the other drop down has the subjects. so when a name is selected from the first dropdown subjects related to that name is loaded to the second dropdown. Its working correctly. But if I again select another name from the first drop down instead of showing only subjects related to the secondly selected name subjects related to first name and second name both shows in the second drop down. Im storing these values in two global arrays and passing them to the two dropdowns. How can I display only the related values in the second drop down ?
js
$scope.arrayName = [];
$scope.arraySubj = [];
function1()
{
//assigning values to $scope.arrayName;
}
function2(selectedVal)
{
//assigning values to $scope.Subj;
}
HTML
<body>
<select ng-model="a" ng-options="item for item in arrayName" ng-change="function2(a)">
<select ng-model="b" ng-options="item for item in $scope.Subj">
</body>
From what I understand, whenever function2(selectedVal) is called you'll need to reset the subj array to empty. Hopefully, that should do the trick.
Would it not be better to just use the built in filter service?
<select ng-model="a" ng-options="name as name in arrayName"></select>
<select ng-model="b" ng-options="item as item in arraySubj | filter: customFilter"></select>
where
$scope.customFilter = function(item, idx, arr) {
return (does item match whatever the criteria is from $scope.a);
}
Instead of rebuilding the $scope.subJ array whenever $scope.a changes?
Related
I'm rendering a map of items retrieved from a database and filtered via the value state of an input field and attempting to then set the state of the input field as the value stored in some list item on click. I figured that using document.getElementById().innerHTML would allow me to retrieve the content stored within the appropriate tag and then set it to state which does work, the issue I'm facing is that it will only retrieve the innerHTML of the first item rendered in the map.
I've tried solutions ranging from applying UUID to making the mapped content available to the window and transfering the state of the individual objects but each disparate solution only moves the value of the first item to state - any ideas?
Rendered Content:
window.filteredItems = this.state.items.filter(
(item) => {
return item.companyNameObj.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1;
}
);
<div className="fixed-width">
<div className="search-container">
<form>
<input type="text" name="search" className="search-bar" placeholder="Search: " onChange={this.handleChange} value={this.state.search} />
</form>
<ul className="search-results">
{window.filteredItems.map((item) => {
return (
<div className="distinct-result-container">
<li key={item.id}>
<div className="image-container">
<img src={item.imageObj} alt={item.companyNameObj + " logo."}/>
</div>
<div className="company-container">
<span onClick={this.stateTransfer}><h3 id={"ID"}>{item.companyNameObj}</h3></span>
<p>Owned by: {item.ownerNameObj}</p>
</div>
</li>
</div>
)
})}
</ul>
</div>
<Footer />
</div>
);
stateTransfer()
stateTransfer(id) {
var search = this.state.search;
var uniqueID = document.getElementById("ID").innerHTML;
this.setState({
search: uniqueID
});
}
The current content of stateTransfer() doesn't represent any significant attempts at approaching a solution to this issue, it's just the minimum required implementation to move the innerHTML content to the input fields value.
EDIT: I've further clarified on the task at hand and a potential solution in the comments below (which follow this), I'm just hoping someone is able to help me with the actual implementation.
#DILEEPTHOMAS The list is comprised of data pulled from a Firebase Realtime Database and is rendered via mapping the filteredList and a search query; that functoionality works fine - what I need is to be able to click the element of any distinct li and have the innerHTML (the text stored in that li's item.companyNameObj) be moved to the value of the input field (so users can navigate the search content with re-typing).
#JoshuaLink I can't necessarily configure the items of the list any
further as it's just data pulled from an external database - I believe
the appropriate solution is to somehow provide a unique HTML ID value
to each newly rendered li and have that selected ID moved to
stateTransfer() where it can be set as the input fields value, I'm
just struggling with the actual implementation of this.
EDIT 2: I've managed to figure out a solution to both parts of the problem as described above - I'll post it as an answer below.
I managed to solve both parts of my problem:
The key issue, which was moving the text stored in each distinct li to the input value, which was apparently easily solved by making my stateTransfer() function accept an event and passing the .innerText value of the h3 through the event (I assumed I would have to use .innerHTML, which would require me to provide each distinct li with a unique generated ID) as follows:
stateTransfer(e) {
var search = this.state.search;
var innerText = e.target.innerText
this.setState({
search: innerText
})
}
The secondary issue, (which I incorrectly assumed was integral to implementing a solution to my question), assigning unique HTML id values to my procedurally generated li's was solved by implementing a for-loop in a componentDidUpdate() function which iterates through the current total length of the list and and assigns an id with the loop iterator concatenated to the end of the string as follows:
componentDidUpdate() {
var i;
var searchCompanyNames = document.querySelectorAll('.comapnyNames');
for(i = 0; i < searchCompanyNames.length; i++) {
searchCompanyNames[i].id = 'companyName-' + i;
}
}
Whilst I didn't need to assign unique ID's to the li's in the correct implementation, it's a useful trick worth noting nonetheless.
I am using PrimeNG's p-orderList. By default, the metaKeySelection attribute is true which implies that a metaKey(ctrl key) is needed to be pressed to select multiple items. I was rather looking for a way to completely disable selection of multiple items. I should be able to select ONLY ONE item in the ordered list.
There is no metaKey attribute available for p-orderList. Can anyone help me with this?
<p-orderList [value]="policyList" [listStyle]="{'min-height':'calc(100vh - 325px)'}" (onSelectionChange)="onSelectionChange($event)">
<ng-template let-policy pTemplate="policy">
<span>{{policy}}</span>
</ng-template>
</p-orderList>
PS: onSelectionChange($event) is triggered every time you select items from the ordered list. $event.value contains the array of the items.
There is no easy flag for it but it can be achieved through calling a function that basically replaces the entire selection array with just the original selected row.
You will need a variable to store the previous value for comparison.
onSelectionChange(event) {
if (event.value.length === 1) {
this.tempValue = event.value[0];
}
else {
event.value = [this.tempValue];
}
}
Can also be simplified by passing event.value to the function
(onSelectionChange)="onSelectionChange($event.value)">
What about the metaKeySelection input property? (as shown here)
<p-orderList [metaKeySelection]="false" [value]="policyList" [listStyle]="{'min-height':'calc(100vh - 325px)'}" (onSelectionChange)="onSelectionChange($event)">
<ng-template let-policy pTemplate="policy">
<span>{{policy}}</span>
</ng-template>
</p-orderList>
So i have a project in which i have to display some data from the table. Now i want to change the size of the data based on a field above the table that is actually a select input field and sends a value to the angular controller. Now this is working perfectly except for the fact that the field doesn't show the selected number of data being displayed on the field.
This is the empty field. but the data is inserted correctly. Also on debugging I found another option here on the field that is not in the html code. Here's my code for the html and the controller.
View:
<li class="manual-dropdown pull-right">
<select id="ddPageSize" ng-model="PaginationInfo.pageSizeSelected" ng-change="ChangePageSize()" aria-controls="DepartmentTable" class="form-control pull-right">
<option value="5">5</option>
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="-1">All</option>
</select>
</li>
Controller:
$scope.PaginationInfo = {
maxSize: 5, // Limit number for pagination display number.
totalCount: 0, // Total number of items in all pages. initialize as a zero
pageIndex: 1, // Current page number. First page is 1.
pageSizeSelected: 5, // Maximum number of items per page.
}
GetData(searched);
function GetData(searched) {
//debugger
//var noOfPages = 1;
var SearchData = $scope.StatusSearch.Search;
if (SearchData == "") {
searched = false;
}
var Displaysize = $scope.PaginationInfo.pageSizeSelected;
var index = $scope.PaginationInfo.pageIndex;
if (searched == false) {
Get("/User/GetData?Size=" + Displaysize + "&index=" + index, false).then(function (d) {
//$("#").val()
//$scope.userAccount.CountryID = $("#ddCountryOptions").val();
// $scope.PaginationInfo.maxSize = d.info.maxSize;
$scope.PaginationInfo.totalCount = d.totalSize;
$scope.PaginationInfo.pageIndex = d.index;
$scope.PaginationInfo.pageSizeSelected = d.size;
//$scope.noOfPages = $scope.PaginationInfo.totalCount / $scope.PaginationInfo.pageSizeSelected;
$scope.accountlist = d.GetList;
$scope.$apply();
})
}
else {
// alert($scope.SearchData.Search);
Get("/User/SearchData?inputstring="+ SearchData, false).then(function (d) {
$scope.accountlist = d.GetList;
$scope.PaginationInfo.pageIndex = index;
$scope.PaginationInfo.pageSizeSelected = Displaysize;
$scope.PaginationInfo.totalCount = d.totalSize;
$scope.$apply();
});
}
}
explanation for the Controller: The data is loaded on page load so the GetData() function is called immediately. the default page size is set to 5 as shown and when i make a change to the field i recall the GetData() function with page size as a argument and the back end does the rest and returns a amount of data that i asked for. Also the reason there are 2 ajax calls in this function is to implement a search function. which check if the input field is empty or has a value and based on that output the data.
What i want to know is why is the page size field on my dropdown empty when i select a value.
Edit:
After a bit more research i found that the ng-Model is making a empty option with the value of the option i selected. Now the problem still remains i don't know how to display the value in the empty object. if i do select another option as selected, my ng-model value does not change. So i am still stuck with this. Also i have already give the ng-model an default value of 5 the same as my first dropdown option. so in case i tag any other option as selected, the ng-model option will remain 5 no matter how many times i change the dropdown value.
Alright i kind of solved my issue, though I am not sure if this is a good way to do it.
So what i did is simply bind the pageSizeSelected Value to the html select element by id.
$("#ddPageSize").val(d.size)
$scope.pageSizeSelected = $("#ddPageSize").val();
before $scope.$apply and it worked. Now when i select a value from the field it changes and displays the value i selected.
I am trying to allocate two crews based on the same data from the server. In the drop-down options, when I select an item in one box. I would like the selected option to disappear in the next drop-down
You could use a filter in the ngOptions expression:
Define your two select box like this , one with a filter
<select ng-model="crew1" ng-options="crew.text for crew in crews1></select>
<select ng-model="crew2" ng-options="crew.text for crew in crews2 | filter:shouldShow"></select>
and define the shouldShow() function to $scope in the controller:
$scope.shouldShow = function (crew) {
// put your authorization logic here
return $scope.crew1 != 'selectedOption';
}
I am trying to get a stored value from the database into a select box, but it is not displaying. The selected value shows in the console(inspect element) but it's just not displaying.
HTML
<td data-ng-class="{'has-error': employeeSchedule.employee.$invalid && employeeSchedule.employee.$dirty}">
<select class="form-control input-sm" name="employee" ng-model="schedule.employee" ng-init="schedule.employee='{{$schedules[0]->employee}}'" ng-options="employee.employeeName for employee in employeesName track by employee.usersId">
<option value="">Select Employee</option>
</select>
</td>
ANGULARJS
app.controller('UpdateWorkScheduleCtrl', [ '$scope', '$http', function ($scope, $http)
{
$http.get('/schedule/employees').success(function(employeedata) {
$scope.employeesName = employeedata;
});
}]);
CONTROLLER(LARAVEL)
public function getEmployees() {
$users = DB::select(DB::raw("SELECT `usersId`, CONCAT(`firstName`,' ',`middleName`,' ',`lastName`) AS employeeName
FROM `users`
WHERE `userStatus` != 'Administrator'
AND `userStatus` != 'Director'
AND `userStatus` != 'HR Specialist'"));
return Response::json($users);
} // end function getEmployees()
INSPECT ELEMENTS(CHROME)
It is clear from inspect elements that the data is there, but it is just not being displayed as the selected item in the select box. Can someone show me what I am doing wrong please.
Your ng-options expression does not match with what you need. You have track by employee.usersId in the syntax employee.employeeName for employee in employeesName track by employee.usersId, Which means that you would need to set ng-model to userId instead of name and also as an object not just as string, i.e your ng-model should ideally be schedule.employee = {usersId:'someid'} for default selection. Now coming to your case which pretty seems like you are trying to set ng-model as a string and you want it the name of the employee (Which probably is a poor choice since you already have an id) you should try the alternate syntax with select as label for value in array`:
ng-options="employee.employeeName as employee.employeeName for employee in employeesName "
Also remember when you use select as syntax you should remove track by, as they are not designed to work together.
Side Note:-
It is a bad idea to use ng-init for initializing ng-mode. And doc says:
The only appropriate use of ngInit is for aliasing special properties of ngRepeat, as seen in the demo below. Besides this case, you should use controllers rather than ngInit to initialize values on a scope.