Angular form of components - javascript

I'm desperate in trying to find a solution.
Here is my profile page structure:
private formSections: any[] = [
{title: 'General information', name: 'general'},
{title: 'Financial Information', name: 'financial'},
{title: 'Languages', name: 'languages'},
{title: 'Education', name: 'education'},
{title: 'Featured Skills', name: 'skills'},
{title: 'Certificates', name: 'certificates'},
{title: 'Experience', name: 'experience'},
...];
Each section should contain a different form with selects, inputs, datepickers, draggable items, chips etc. But in the same time it should be a one large form that will be published to the server.
Since it's a pretty big amount of form elements and they are separated visually in my layout, it would be wise to split them to components.
But I cannot find any examples online of how to achieve that.
Here is how my main component looks like:
// profile.component.html
<form [formGroup]="profileForm" novalidate (ngSubmit)="save(profileForm)">
<div id="{{section.name}}" *ngFor="let section of formSections">
<div class="editprofile-title">{{section.title}}</div>
<div class="editprofile-form" >
<div *ngIf="section.name=='general'"
[group]="profileForm"
profileGeneralFormComp ></div>
<div *ngIf="section.name=='financial'"
profileFinancialFormComp
[group]="profileForm"></div>
<div *ngIf="section.name=='languages'"
profileLanguagesFormComp
[group]="profileForm"></div>
<div *ngIf="section.name=='education'"
profileEducationFormComp
[group]="profileForm"></div>
<div *ngIf="section.name=='skills'"
profileSkillsFormComp
[group]="profileForm"></div>
<div *ngIf="section.name=='certificates'"
profileCertificatesFormComp
[group]="profileForm"></div>
<div *ngIf="section.name=='experience'"
profileExperienceFormComp
[group]="profileForm"></div>
<div *ngIf="section.name=='links'"
profileLinksFormComp
[group]="profileForm"></div>
</div>
</div>
</form>
Main struggle is that i can't pass a parent formGroup to my component and fill it with formControls inside.
Any help/advice will be appreciated.

Related

Vue how to traverse the list correctly?

I just writed the vue simple code, But unable to follow the HTML effect. After traversal rendering a bit wrong. If gift object is no, for example the goods object has two data, goods_b1 + goods_b2. But i want to follow the HTML effect. Go to the HTML still. And go to the vue loops.
I want to the this effect:
Look at the javascript:
var app = new Vue({
el: "#app",
data: {
list: [{
id: 1,
name: 'A',
goods: [{
name: "goods_a1"
}],
gift: [{
name: "gift_a1",
}]
}, {
id: 2,
name: 'B',
gift: [],
goods: [{
name: "goods_b1"
}, {
name: "goods_b2"
}],
}, {
id: 3,
name: 'C',
goods: [{
name: "goods_c1"
}, {
name: "goods_c2"
}, {
name: "goods_c3"
}],
gift: [{
name: "gift_c1",
}]
}]
}
})
HTML:
<div id="app">
<div class="mui-row" v-for="item in list">
<div class="span-title-main">
<span class="span-title">{{item.name}}</span>
</div>
<br>
<ul>
<li>
<div class="mui-col" v-for="items in item.goods">
<span class="span-name">{{items.name}}</span>
</div>
<div class="addspan">+</div>
<div class="mui-col" v-for="itemss in item.gift">
<span class="span-name">{{itemss.name}}</span>
</div>
<div class="addspan">+</div>
</li>
</ul>
</div>
</div>
Are you asking that the (+) being inside the loop of your goods and gift ?
<div id="app">
<div class="mui-row" v-for="item in list">
<div class="span-title-main">
<span class="span-title">{{item.name}}</span>
</div>
<br>
<ul>
<li>
<div class="mui-col" v-for="items in item.goods">
<span class="span-name">{{items.name}}</span>
<div class="addspan">+</div>
</div>
<div class="mui-col" v-for="itemss in item.gift">
<span class="span-name">{{itemss.name}}</span>
</div>
</li>
</ul>
</div>
</div>
Edit: Remove the (+) for gifts loop as requested by OP.
Note: if the OP is asking to have a style for element in between goods and gift. I would suggest to use the css :last selector with a display:none to have this kind of effect.
It looks like the only difference is that you want a + button to appear after each item.goods instead of just one after the loop.
So put it inside the loop:
<template v-for="items in item.goods"><!-- using "template" to avoid modifying your html structure; you could of course use any tag -->
<div class="mui-col">
<span class="span-name">{{items.name}}</span>
</div>
<div class="addspan">+</div>
</template>
<div class="mui-col" v-for="items in item.gift">
<span class="span-name">{{items.name}}</span>
</div>
<!-- your image doesn't show a + button after gifts, so I've omitted it here -->

Vue.js change model attached to a form upon clicking a list

I have an array of objects. These objects are loaded into a list in vue.js.
Aside from this list, I have a form that displays data from one of these objects. I want to, when clicking one of the list's elements, it will bind this specific object to the form and show its data.
How can do this in Vue.js?
My list code is:
<div id="app-7">
<ul id="food-list" v-cloak>
<food-item v-for="item in foodList" v-bind:food="item" v-bind:key="item.id" inline-template>
<li class="food">
<div class="food-header">
<img :src="'img/' + food.slug +'.png'">
<div class="food-title">
<p>{{food.name}} |
<b>{{food.slug}}</b>
</p>
<p>quantity: {{food.quantity}}</p>
</div>
<div class="food-load"> // load into form upon clicking this
</div>
</div>
</li>
</food-item>
</ul>
</div>
Since I do not have the code for the form, this is my best guess without clarification.
You can add a click handler to the item you want to be clicked. It will pass the value of the food item into the method.
<div class="food-load" #click="setFoodItem(item)">
</div>
And when that method is called, it can assign the clicked item to a data property. I'm not sure where your form is, and if it is in a different component. If it is in a child component, you would have to pass it in as a prop, or emit an event to pass it to a parent component.
data() {
return {
//create a reactive field to store the current object for the form.
foodItemForm: null
};
},
methods: {
//method for setting the current item for the form.
setFoodItem(item) {
this.foodItemForm = item;
}
}
Missing quite a bit of info in your sample code, your script is very important to see to make sense of what you would like to accomplish and where things might be going wrong.
Here's a quick list of the issue I came across with your code:
v-for refers to an individual food item as 'item', inside the loop you're trying to access properties as 'food'
You don't wrap your code in a component unless you're importing the component
When binding a value to 'v-bind:src' (or shorthand ':src') only pass the url, you should be specifying this in your script not inline.
You're better off using a button and the 'v-on:click' (or shorthand '#click') to load your selected food item into your form
You should also include your Javascript
Regardless, here's how I would handle this (took the liberty in filling in some blanks):
<template>
<div id="app">
<ul id="food-list">
<!--<food-item v-for="item in foodList" v-bind:food="item" v-bind:key="item.id" inline-template>-->
<li v-for="item in foodList" class="food">
<div class="food-header">
<img :src="item.slug" v-bind:alt="item.slug" width="250px" height="auto">
<div class="food-title">
<p>{{item.name}} | <b>{{item.slug}}</b></p>
<p>quantity: {{item.quantity}}</p>
</div>
<button class="food-load" #click="loadFoodItem(item.id)">Load Food Item</button>
</div>
</li>
<!--</food-item>-->
</ul>
<form v-if="activeFoodId != null" id="foodItemForm" action="#">
<h3>Food Form</h3>
<label for="food-id">Id:</label>
<input id="food-id" type="number" v-bind:value="foodList[activeFoodId].id"><br/>
<label for="food-slug">Slug:</label>
<input id="food-slug" type="text" v-bind:value="foodList[activeFoodId].slug"><br/>
<label for="food-name">Name:</label>
<input id="food-name" type="text" v-bind:value="foodList[activeFoodId].name"><br/>
<label for="food-quantity">Quantity:</label>
<input id="food-quantity" type="number" v-bind:value="foodList[activeFoodId].quantity">
</form>
</div>
</template>
<script>
export default {
name: 'app',
data: function () {
return {
activeFoodId: null,
foodList: [
{
id: 1,
slug: 'http://3.bp.blogspot.com/-QiJCtE3yeOA/TWHfElpIbkI/AAAAAAAAADE/Xv6osICLe6E/s320/tomato.jpeg',
name: 'tomatoes',
quantity: 4
}, {
id: 2,
slug: 'https://img.purch.com/rc/300x200/aHR0cDovL3d3dy5saXZlc2NpZW5jZS5jb20vaW1hZ2VzL2kvMDAwLzA2NS8xNDkvb3JpZ2luYWwvYmFuYW5hcy5qcGc=',
name: 'bananas',
quantity: 12
}, {
id: 3,
slug: 'https://media.gettyimages.com/photos/red-apples-picture-id186823339?b=1&k=6&m=186823339&s=612x612&w=0&h=HwKqE1MrsWrofYe7FvaevMnSB89FKbMjT-G1E_1HpEw=',
name: 'apples',
quantity: 7
}
]
}
},
methods: {
loadFoodItem: function (foodItemId) {
console.log(foodItemId)
this.activeFoodId = foodItemId
}
}
}
</script>
<style>
/# Irrelevant #/
</style>
Hope it helps!

Bind list to multiple target divs in WinJS

I have list declared in js file like this (full list contain 6 items, but can be more or less than that)
var dataArray = [
{
type: "item", title: "Cliff",
picture: "../../images/slike_etnologija/srednji_vek/01.jpg",
text: "some description"
},
{
type: "item", title: "Grapes",
picture: "../../images/slike_etnologija/srednji_vek/02.jpg",
text: "another description"
},
two templates declared in html file
<div id="galleryTemplate" data-win-control="WinJS.Binding.Template">
<div class="overlaidItemTemplate">
<img class="image img-responsive" src="#" data-win-bind="src: picture; alt: title" />
<div class="overlay">
<h2 class="ItemTitle" data-win-bind="innerText: title"></h2>
</div>
</div>
</div>
<div id="textTemplate" data-win-control="WinJS.Binding.Template">
<div>
<p data-win-bind="innerText: text"></p>
</div>
</div>
and two controls where i need to show data from list
<div class="col-md-12" id="basicFlipView"
data-win-control="WinJS.UI.FlipView"
data-win-options="{ itemDataSource : EtnologijaGallery.itemList.dataSource, itemTemplate: galleryTemplate }">
</div>
<p data-win-control="WinJS.UI.ListView"
data-win-options="{ itemDataSource : EtnologijaGallery.itemList.dataSource, itemTemplate: textTemplate }">
</p>
I'm trying to show image gallery in flipbox and text description associated to each image in listview next to it. Due to design i can't put both things in same template.
My flipbox works fine, and shows all images, but listview don't work. It shows, first, only 3 descriptions from list, and those 3 descriptions are shown in control with scroll bar, instead changing when user change image in flipbox.
Can someone help me solve this?
As mentioned on http://www.buildwinjs.com/tutorial/2WinJS_Binding/bindingInit/, WinJS Binding is one-time binding and you bound the same array to two separate controls.
I think you should check FlipView's onpageselected event and when that event occurs, update the div with the proper text. I guess the ListView is not needed to be used in this case at all.

Displaying a grid of images sorted by category using angularjs

I am building a web application using angular and I want to display a grid of items sorted by category. Each row will correspond to a certain category. This is what my code looks like:
<ion-item ng-repeat="item in items|filter:query|orderBy:'name' ">
<div class="row" ng-scrollable style="width:400px;height:300px;">
<div class="col">
<img ng-src={{item.img}}/>
<p>{{item.name}}</p>
<p>Old Price: {{item.newPrice}}</p>
<p>New Price: {{item.newPrice}}</p>
<button class ="button" ng-click="addToGrocery()">Add to List</button>
</div>
</div>
My controller.js file looks like this:
.controller('CouponsCtrl', function($scope) {
$scope.items = [{ name: 'Banana', newPrice: 3.29, oldPrice: 4.49, aisle: 'A', img: 'http://placehold.it/280x150', category: 'Fruits' },
{ name: 'Chocolate', newPrice: 3.19, oldPrice: 5.39, aisle: 'B', img: 'http://placehold.it/280x150' , category: 'Dairy'},
{ name: 'Brocolli', newPrice: 2.29, oldPrice: 4.40, aisle: 'D', img: 'http://placehold.it/280x150' , category: 'Vegetables'}
];
})
I believe I need nested ng-repeats but I am not sure how to incorporate that.
Base on groupby Group item detail using AngularJs ng-repeat
<body ng-controller="con">
<div ng-repeat="(setKey, set) in items|filter:query|orderBy:'name'|groupBy:'category'">
{{setKey}}
<div ng-repeat="item in set">
<div class="row" ng-scrollable="" style="width:400px;height:300px;">
<div class="col">
<img ng-src="{{item.img}}/" />
<p>{{item.name}}</p>
<p>Old Price: {{item.newPrice}}</p>
<p>New Price: {{item.newPrice}}</p>
<button class="button" ng-click="addToGrocery()">Add to List</button>
</div>
</div>
</div>
</div>
</body>
http://plnkr.co/edit/GMW52iJyRlQ2otZndGLM?p=preview

Grouping ng-repeat and modifying DOM outside directive

I'm not exactly sure how to describe the issue I am having, or even if it is an issue. I guess I am having trouble wrapping my head around how Angular Directives work. Any advice and/or opinion on best practice is welcomed.
I have a simple array of objects in my controller's $scope:
$scope.birthdays = [
{ name: "bob", dob:moment("09/20/1953"), cake: "vanilla"},
{ name: "michael", dob:moment("09/20/1953"), cake: "chocolate" },
{ name: "dave", dob:moment("09/20/1953"), cake: "chocolate" },
{ name: "chief", dob:moment("04/24/1977"), cake: "chocolate" },
{ name: "jerry", dob:moment("04/24/1977"), cake: "red velvet" },
{ name: "jerkface", dob:moment("04/24/1977"), cake: "i hate cake" },
{ name: "doug", dob:moment("05/10/1994"), cake: "marble" },
{ name: "jeff", dob:moment("05/10/1994"), cake: "vanilla" }
];
Say I would like to create a DOM structure from this data model:
<h1>Birthday: 09/20/1953</h1>
<div class="birthday">
<h2>Name: bob</h2>
<h3>Cake: vanilla</h3>
</div>
<div class="birthday">
<h2>Name: michael</h2>
<h3>Cake: chocolate</h3>
</div>
<div class="birthday">
<h2>Name: dave</h2>
<h3>Cake: chocolate</h3>
</div>
<h1>Birthday: 04/24/1977</h1>
<div class="birthday">
<h2>Name: chief</h2>
<h3>Cake: chocolate</h3>
</div>
....
I can achieve something close to this in this plunker.
There, however, I end up with a slightly different DOM structure that I don't want.
<div ng-repeat="birthday in birthdays" birthday-boy="">
<h3 ng-show="!birthdays[$index-1].dob.isSame(birthday.dob)" class="ng-binding" style="">
September 20th, 1953
</h3>
<div class="ng-binding">
Name: bob
</div>
<div class="ng-binding">
Cake: vanilla
</div>
</div>
<div ng-repeat="birthday in birthdays" birthday-boy="">
<h3 ng-show="!birthdays[$index-1].dob.isSame(birthday.dob)" class="ng-binding" style="display: none;">
September 20th, 1953
</h3>
<div class="ng-binding">
Name: michael
</div>
<div class="ng-binding">
Cake: chocolate
</div>
</div>
<div ng-repeat="birthday in birthdays" birthday-boy="">
<h3 ng-show="!birthdays[$index-1].dob.isSame(birthday.dob)" class="ng-binding" style="">
April 24th, 1977
</h3>
<div class="ng-binding">
Name: chief
</div>
<div class="ng-binding">
Cake: chocolate
</div>
</div>
So, my questions are:
Am I thinking about this problem correctly? Should I be modifying my data structure to group it by dates there, and then just ng-repeat over each individual date?
If there is a way to do this with my existing data structure, do I need to modify the DOM outside of the birthday-boy / ng-repeat directive?
Is there a way to wrap the ng-repeat directive into something custom - I have started looking into the compile function but, just not sure...
Thanks!
I would group by dates in your controller, then ng-repeat over that new scope property. Here is a fiddle I wrote for a similar "group by" question. You should be able to adapt it for your code. I used the orderByFilter
$scope.sortedFriends = orderByFilter($scope.friends, '+age');
but you'll likely need to use the dateFilter or whatever JavaScript code you might have around to sort by the dob stuff.

Categories

Resources