How to iterate two separate arrays in handlebars Nodejs with {{#each}}? - mysql

I am creating a Risk Management System using Nodejs and Express with Handlebar views. Using SQL, I am extracting two queries in my GET router and rendering them to the handlebar view. This is how it looks:
const parametro = await pool.query('select * from parametro where parid = ?', [parid]);
const tipoParametros = await pool.query('select distinct tipoparid from tipoparametro order by tipoparid');
res.render('parametros/modificar', {parametro, tipoParametros});
I consoled logged both arrays and they look like these:
- parametro: [
RowDataPacket {
parid: 22,
parcodigo: 'TEST',
tipoparid: 11,
pardescripcion: 'Just a Test',
parexplicacion: 'Test',
parclasificacion: 3,
parvalor: 'Test 1',
parusrcreaid: null,
parfechacrea: 2022-06-25T21:58:19.000Z,
parusrmodid: null,
parfechamod: null
}
]
- tipoParametros: [ RowDataPacket { tipoparcodigo: 'SYS', tipoparid: 11 } ]
However, since my POST for this view needs :id, I am iterating with each parametro because that's how I keep track of each row in my database, with parid. The .hbs view looks like this:
{{#each parametro}}
<form class = "row g-3 needs-validation" method = "POST" action = "/parametros/modificar/{{this.parid}}" novalidate>
{{> formparametro}}
</form>
{{/each}}
and inside "formparametro" there is a form-floating section where I try to iterate with each tipoParametro but nothing is coming out. Looks like this:
<div class="col-6">
<div class="form-floating">
<select class="form-select" id="floatingSelect" name="tipoparid" aria-label="Floating label select example" required>
{{#each tipoParametros}}
<option value={{this.tipoparid}}>{{this.tipoparcodigo}}</option>
{{/each}}
</select>
<label for="floatingSelect">Tipo Parametro</label>
</div>
</div>
How can I have access to the query and columns of tipoParametro?

As your formparametro partial is rendered within your {{#each parametro}} block, the context for each time the partial is rendered is the currently iterated item from parametro. Therefore, the partial has no access to tipoParametros.
What we want to do is provide a context to our partial that does contain tipoParametros. This is very simple. The Handlebars documentation covers Partial Contexts and it states that a context can be supplied to the partial as the second parameter within the mustache brackets, as in:
{{> myPartial myOtherContext }}
As your tipoParametros object belongs to your root context, I would recommend using the #root data variable to pass the root context to your partial. The line in your template invoking your partial thus becomes:
{{> formparametro #root}}
I have created a fiddle for your reference.

Related

HTML Multiple select not returning array

I'm trying to make a web application using express and I'm trying to make a form to create a new product. In there I have multiple select to select the categories for the product.
Here is my code for the multi-select:
<div class="form-group row mb-3">
<label for="categories" class="col-form-label sol-sm-2">Categories:</label>
<div class="col-sm-10">
<select multiple name="product[categories[]]" id="categories" class="form-control">
<% for (let category of categories) { %>
<option value="<%= category.id %>">
<%= category.name %>
</option>
<% } %>
</select>
</div>
</div>
The target is for it to fill in the products.categories field with an array of categories.
But this is what I receive on the server:
{
product: {
name: 'Nvidia GeForce RTX 4090',
price: '1499.99',
description: 'State-of-the-art GPU. Recently released with unrivalled performance. Take your gaming to the next level!',
discountedPrice: '',
stock: '5'
},
'product[categories': [ '63a18514fade00e8bc7f4d1c' ]
}
It doesn't seem to want to format the array properly and I'm unsure as to why this is.
I've already tried removing the second brackets in the name field to get
product[categories]
But then it doesn't return an array when just a single item is selected.
Is there an alternative way of me doing this or should I just use the above and convert it to an array on the server?
It works without extra server-side code if you change the name to
<select multiple name="product[categories]">
(without the nested brackets). Then the request
GET path?product[categories]=a&product[categories]=b
will be parsed into
req.query = {"product":{"categories":["a","b"]}}
and the request
POST path
Content-Type: application/x-www-form-urlencoded
product[categories]=a&product[categories]=b
will be parsed into
req.body = {"product":{"categories":["a","b"]}}
if you use the body-parsing middleware express.urlencoded({extended: true}) with the extended: true option.

V-for from a nested array

I'm starting with vue.js and I need to populate selects with v-for that are inside another v-for.
I was reading questions about this subject but could not find a way to make it works in my case.
I have a nested array (tours) with title and description and I have a v-for inside another one to populate a select with tours' title:
html:
<div class="row" id="app">
<div v-for="(item, index) in hosters" v-bind:key="item.id" class="col-md-6 mb-50">
<h4 class="mb-0">{{ item.name }} {{ item.lastname }}</h4>
<div class="tour-options-select">
<select id="select-suggestions" name="tour-options-dropdown" class="tour-options-dropdown">
<option v-for="tour in tours">{{ tour.title }}</option>
</select>
</div>
</div>
</div>
vue.js:
let app = new Vue({
el: '#app',
data: {
city: 'mycity',
hosters: null,
tours: [],
title: [],
},
created: function () {
this.searchHoster()
},
methods: {
searchHoster: function () {
axios.post('searchHoster.php', { "city": this.city }).then((response) => {
this.hosters = response.data.hosters;
console.log(this.hosters);
this.tours = this.hosters.map(res => res.tours);
console.log(this.tours);
this.title = this.tours.map(res => res.title);
console.log(this.title);
}).catch((error) => {
console.log(error);
});
},
}
})
I’m getting undefined in console.log(this.title); line so i tried to use:
this.title = response.data.hosters.map(hoster => hoster.tours).flat().map(item => item.title);
but it gives me a simple array with all the titles of all users. So, all selects are populated with the same titles for everyone. Any tip about how to make it works?
Change tours to item.tours on second v-for:
<div v-for="(item, index) in hosters" v-bind:key="item.id" class="col-md-6 mb-50">
<h4 class="mb-0">{{ item.name }} {{ item.lastname }}</h4>
<div class="tour-options-select">
<select id="select-suggestions" name="tour-options-dropdown" class="tour-options-dropdown">
<option v-for="tour in item.tours">{{ tour.title }}</option>
</select>
</div>
</div>
Do not break out the various pieces of data you are interested in rendering. Instead, render the inner portions using the index value from the outer v-for. For example, assuming your data looks like the data you depicted, then...
V-for="item in data"
Render host info using item.name, etc.
v-for="tour in item.tours"
Render title and description from tour.title, etc.
Much faster and easier. I might also suggest using an accordion type control as well - render a table of all the tours, and allow user to select the desired row by check box (which would then display further details in a details area). - that way they can see all the options easily. Make the items collapsible using #click to toggle a boolean value which controls show=boolean on a nested div.
Good luck.
<div class="tour-options-select">
<select id="select-suggestions" name="tour-options-dropdown" class="tour-options-dropdown">
<option v-for="tour in ̶t̶o̶u̶r̶ item.tours">{{ tour.title }}</option>
</select>
</div>
Change the tours to item.tours
Since you are already iterating through the first v-for the context for the 2nd v-for is "item". and item.tours would give you the proper object to iterate over.

Angularjs convert string to object inside ng-repeat

i've got a string saved in my db
{"first_name":"Alex","last_name":"Hoffman"}
I'm loading it as part of object into scope and then go through it with ng-repeat. The other values in scope are just strings
{"id":"38","fullname":"{\"first_name\":\"Alex\",\"last_name\":\"Hoffman\"}","email":"alex#mail","photo":"img.png"}
But I want to use ng-repeat inside ng-repeat to get first and last name separate
<div ng-repeat="customer in customers">
<div class="user-info" ng-repeat="name in customer.fullname">
{{ name.first_name }} {{ name.last_name }}
</div>
</div>
And I get nothing. I think, the problem ist, that full name value is a string. Is it possible to convert it to object?
First off... I have no idea why that portion would be stored as a string... but I'm here to save you.
When you first get the data (I'm assuming via $http.get request)... before you store it to $scope.customers... let's do this:
$http.get("Whereever/You/Get/Data.php").success(function(response){
//This is where you will run your for loop
for (var i = 0, len = response.length; i < len; i++){
response[i].fullname = JSON.parse(response[i].fullname)
//This will convert the strings into objects before Ng-Repeat Runs
//Now we will set customers = to response
$scope.customers = response
}
})
Now NG-Repeat was designed to loop through arrays and not objects so your nested NG-Repeat is not necessary... your html should look like this:
<div ng-repeat="customer in customers">
<div class="user-info">
{{ customer.fullname.first_name }} {{ customer.fullname.last_name }}
</div>
This should fix your issue :)
You'd have to convert the string value to an object (why it's a string, no idea)
.fullname = JSON.parse(data.fullname); //replace data.fullname with actual object
Then use the object ngRepeat syntax ((k, v) in obj):
<div class="user-info" ng-repeat="(nameType, name) in customer.fullname">
{{nameType}} : {{name}}
</div>
My advise is to use a filter like:
<div class="user-info"... ng-bind="customer | customerName">...
The filter would look like:
angular.module('myModule').filter('customerName', [function () {
'use strict';
return function (customer) {
// JSON.parse, compute name, foreach strings and return the final string
};
}
]);
I had same problem, but i solve this stuff through custom filter...
JSON :
.........
"FARE_CLASS": "[{\"TYPE\":\"Economy\",\"CL\":\"S \"},{\"TYPE\":\"Economy\",\"CL\":\"X \"}]",
.........
UI:
<div class="col-sm-4" ng-repeat="cls in f.FARE_CLASS | s2o">
<label>
<input type="radio" ng-click="selectedClass(cls.CL)" name="group-class" value={{cls.CL}}/><div>{{cls.CL}}</div>
</label>
</div>
CUSTOM FILTER::
app.filter("s2o",function () {
return function (cls) {
var j = JSON.parse(cls);
//console.log(j);
return j;
}
});

Issue when trying to populate a drop-down with database values

I am using the following HTML to show a selected drop down with values from the database and rest of the others in the list. It shows the selected name correctly but the selected is also displayed in the list.
How to remove the second time show selected name in the drop down list? Is this a good way to use drop down menu? Here Jobcategory and Jobdetails are associated.
Im using Laravel 4.2 and this is the HTML:
// view drop down form to save data
<div class="large-6 columns">
<label>Job Category
<select name="category[]">
<option value="">Select Category</option>
#foreach(JobCategory::all() as $jcat)
<option value="{{ $jcat->id }}">{{ $jcat->name }}</option>
#endforeach
</select>
</label>
</div>
// Edit drop down form to update the selected value
<div class="large-6 columns">
<label>Job Category
<select name="category[]">
<option value="{{$jobedit->jobcategory->id}}">{{$jobedit->jobcategory->name </option>
#foreach(JobCategory::all() as $jcat)
<option value="{{ $jcat->id }}">{{ $jcat->name }}</option>
#endforeach
</select>
</label>
</div>
// database table for jobcategories
id | name
1 | Accounting/Finance
2 | Advertisement/Event Mgt.
3 | .....
// after save into jobdetails table
id | jobcategory_id | .......
1 | 5 | ...
I can retrieve the value of jobcategory in the edit form but it shows twice one in the selected value and other in the listed value of all jobcategory. This is the problem and i want only show the selected value and then rest of the others from jobcategory table without duplicate value of selected in the drop down. plz help.
// controller to to edit
public function getJobEdit($id)
{
$jobedit = JobDetail::find($id);
return View::make('employers.edit_single_jobs')->with('jobedit', $jobedit);
}
// JobDetail --model
public function jobcategory()
{
return $this->belongsTo('JobCategory');
}
// JobCategory --model
public function jobdetails()
{
return $this->hasMany('JobDetail', 'jobcategories');
}
Have a look at the Forms & HTML helper of laravel.
Generating A Drop-Down List With Selected Default
echo Form::select('size', array('L' => 'Large', 'S' => 'Small'), 'S');
where the first argument is the name of the select box. The second argument is an array of all entries in the box and the last argument determines which of the array elements is the selected one.
in your case it could look something like this:
{{ Form::select(
'categoryName',
array(
'Accounting/Finance' => 'Accounting/Finance',
'Advertisement/Event Mgt.' => 'Advertisement/Event Mgt.',
// to be continued ...
),
'$cat->category_name'
); }}
//Edit
<div class="large-6 columns">
<label>Job Category
{{ Form::select('category[]', ['' => 'Select a category'] + $all_categories, $jobedit->jobcategory->id) }}
</select>
</label>
</div>
where $all_categories should be an array of all categories as in the first example. You can get this from JobCategory::all().
This is how I set up drop-downs in my projects. I prepare the data in my controller (you'd obviously need a route and controller set up for this, I'm assuming you've done that):
Controller
public function index()
{
$categories = \Category::lists('name', 'id')->orderBy('name'); // assuming you have a Category model
view('categories', compact('categories'));
}
Then you can use the Forms and HTML helper as Peh mentioned, this isn't available as a default in Laravel 5 so you'd need to add it into your project using composer. To do so either run composer install illuminate/html or add "illuminate/html": "~5.0" to your composer.json file and then run composer install. You'd then need to add 'Illuminate\Html\HtmlServiceProvider' to config/app.php in the providers array then add 'Form' => 'Illuminate\Html\FormFacade' and 'HTML' => 'Illuminate\Html\HtmlFacade' to the aliases array in the same file. Once that's sorted you can use the Form and HTML helper in your view, as so:
View
{{ Form::select('categoryName', ['' => 'Select a category'] + $categories) }}
Your view would need to be saved as filename.blade.php if using the handlebars, otherwise echo it within <?php ?> tags.
Hope that helps you on your way.

Loading values into select menu from json data

I have a multi-form that I am trying to build using ember.js. I've created the first step of the form using an array of data in my ObjectController but I now need to get the data from a JSON object provided by a rails app. I'm having a bit of trouble understanding how I can use ember-data to retrieve the JSON object and load just the options data into my select menu.
Here's my HTML:
<div class="col-md-12 col-xs-12 content">
<div class="text-center center-block">
<div class="col-md-12">
<span>Which of these</span>
<h2>Activities Appeal</h2>
<span>to you the most?</span>
<div class="form-group single-step">
{{view Ember.Select
content=studies
optionValuePath="content.value"
optionLabelPath="content.label"
prompt="Area of Study"
name="answer[3]"
id="answer_3"
class="form-control span12"
}}
</div>
</div>
</div>
Here's my JS:
var Mobile = Ember.Application.create({
LOG_TRANSITIONS: true
});
/** Setup the urls for the mobile screens **/
Mobile.Router.map(function(){
this.resource('index', { path: "/" });
});
/* Extend the controllers to load objects */
Mobile.IndexController = Ember.ObjectController.extend({
selecedStudies:null,
studies: [
{value:'14', label: 'Business'},
{value:'15', label: 'Criminal Justice'},
{value:'16', label: 'Education'},
{value:'17', label: 'Engineering & Science'},
{value:'18', label: 'Fire & Emergency Mgmt'},
{value:'19', label: 'Healthcare'},
{value:'20', label: 'Information Technology'},
{value:'21', label: 'Legal/Paralegal Studies'},
{value:'22', label: 'Liberal Arts'},
{value:'24', label: 'Psychology & Counseling'},
{value:'25', label: 'Social Services'},
{value:'26', label: 'Web/Graphic Design'},
{value:'27', label: 'Theology'},
{value:'23', label: 'Nursing'}
]
});
And Here is the JSON data as it will come from the rails app:
{"form_id":17,"questions":[{"question":{"id":3,"identifier":"","name":"Area of Study","question_validation_id":null,"require_question":true,"set_as_qualification":false,"type_id":3,"from_option":true,"options":[{"option":{"id":14,"name":"Business"}},{"option":{"id":15,"name":"Criminal Justice"}},{"option":{"id":16,"name":"Education"}},{"option":{"id":17,"name":"Engineering & Science"}},{"option":{"id":18,"name":"Fire & Emergency Mgmt"}},{"option":{"id":19,"name":"Healthcare"}},{"option":{"id":20,"name":"Information Technology"}},{"option":{"id":21,"name":"Legal/Paralegal Studies"}},{"option":{"id":22,"name":"Liberal Arts"}},{"option":{"id":24,"name":"Psychology & Counseling"}},{"option":{"id":25,"name":"Social Services"}},{"option":{"id":26,"name":"Web/Graphic Design"}},{"option":{"id":27,"name":"Theology"}},{"option":{"id":23,"name":"Nursing"}}],"option_view":"grid"}}]}
The end goal is to be able to get and post data for each step in a multi-form but for now I just need to be able to get my data from the JSON object and display it in the step of the form.
I have a working example of my static form available here: http://jsbin.com/qefod/5/edit
Any insight on the proper Ember way to loading a JSON object with Ember Data would be much appreciated.
::: UPDATE :::
I have a bit of an update where I've changed the routes to reflect the source data nesting and I've added model definitions and API request. You can see the updated JSBin here: http://jsbin.com/qefod/7/edit
What I need to do in this example is to load the options from the JSON data into the select menu. For some reason my Ember console does load the data into the model but I can not access it through the template.
To get the value selected in your select element, you need to add value to your view Ember.select like so:
{{view Ember.Select
content=studies
optionValuePath="content.value"
optionLabelPath="content.label"
prompt="Area of Study"
name="answer[3]"
value=selecedStudies
id="answer_3"
class="form-control span12"
}}
Then you can access this inside your step2 action in your controller:
actions: {
step2: function() {
console.log(this.get('selecedStudies'));
}
}