我在Angular 2中有一个表单,其中包含由用户动态添加的字段。添加的对象如下所示:
[ { "equipment_type_id": 1, "action": "added", "quantity": 3}]
设备类型可以重复使用不同的数量,我需要按equipment_type_id分组并使用数量计算总数。
我已经使用了reduce函数进行分组,但不确定如何计算总数而不是仅仅将数量添加到新对象中
var groups = this.inspection.equipments.reduce(function(obj,item){
obj[item.equipment_type_id] = obj[item.equipment_type_id] || [];
obj[item.equipment_type_id].push(item.quantity);
return obj;
}, {});
任何帮助都会很棒
答案 0 :(得分:0)
首先,您需要检查是否已添加该类型的项目:
<html><head>
<meta charset="utf-8">
<meta content="IE=edge" http-equiv="X-UA-Compatible">
<meta content="width=device-width,initial-scale=1.0" name="viewport">
<title>Reset password</title>
<style type="text/css">
html
{
box-sizing: border-box;
line-height: 1.15;
}
*,
*::before,
*::after
{
box-sizing: inherit;
}
body
{
margin: 0;
font-family:
'Segoe UI',
Roboto,
Helvetica,
Arial,
sans-serif;
}
h1
{
font-size: 2em;
margin: 0.67em 0;
}
hr
{
height: 0;
}
abbr[title]
{
text-decoration: underline dotted;
}
b,
strong
{
font-weight: bolder;
}
code,
kbd,
samp,
pre
{
font-family: SFMono-Regular, Consolas, 'Liberation Mono', Menlo, Courier, monospace; /* 1 */
font-size: 1em; /* 2 */
}
small
{
font-size: 80%;
}
sub,
sup
{
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub
{
bottom: -0.25em;
}
sup
{
top: -0.5em;
}
button,
input,
optgroup,
select,
textarea
{
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
button,
select
{
text-transform: none;
}
button,
[type='button'],
[type='reset'],
[type='submit']
{
-webkit-appearance: button;
}
button::-moz-focus-inner,
[type='button']::-moz-focus-inner,
[type='reset']::-moz-focus-inner,
[type='submit']::-moz-focus-inner
{
border-style: none;
padding: 0;
}
button:-moz-focusring,
[type='button']:-moz-focusring,
[type='reset']:-moz-focusring,
[type='submit']:-moz-focusring
{
outline: 1px dotted ButtonText;
}
fieldset
{
padding: 0.35em 0.75em 0.625em;
}
legend
{
padding: 0;
}
progress
{
vertical-align: baseline;
}
[type='number']::-webkit-inner-spin-button,
[type='number']::-webkit-outer-spin-button
{
height: auto;
}
[type='search']
{
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
[type='search']::-webkit-search-decoration
{
-webkit-appearance: none;
}
::-webkit-file-upload-button
{
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
:root
{
tab-size: 4;
}
details
{
display: block;
}
summary
{
display: list-item;
}
h1, h2, h3, h4, h5, h6
{
font-weight: 400;
}
p, ul, ol
{
margin: 0.25rem 0;
}
h1
{
margin: 1.5rem 0;
font-size: 2rem;
line-height: 1.25;
}
h2
{
margin: 1.2rem 0;
font-size: 1.75rem;
line-height: 1.15384615;
}
h3
{
margin: 1rem 0;
font-size: 1.5rem;
line-height: 1.13636364;
}
h4
{
margin: 0.8rem 0;
font-size: 1.375rem;
line-height: 1.11111111;
}
h5
{
margin: 0.65rem 0;
font-size: 1.125rem;
line-height: 1;
}
blockquote
{
font-size: 1.25em;
line-height: 1.25;
}
@media (min-width: 43.75em)
{
h1
{
font-size: 2.5em;
line-height: 1.125;
}
h2
{
font-size: 2em;
line-height: 1.25;
}
h3
{
font-size: 1.5em;
line-height: 1.25;
}
h4
{
line-height: 1.22222222;
}
blockquote
{
font-size: 1.5em;
line-height: 1.45833333;
}
}
@media (min-width: 56.25em)
{
h1
{
font-size: 3em;
line-height: 1.05;
}
h2
{
font-size: 2.25em;
line-height: 1.25;
}
h3
{
font-size: 1.75em;
line-height: 1.25;
}
}
.bold
{
font-weight: bold;
}
.btn
{
cursor: pointer;
text-decoration: none;
text-align: center;
border: none;
border-radius: 6px;
padding: 0.5rem 1rem 0.35rem;
box-shadow: inset 0 0 0 1px #27496D;
}
.btn:not([disabled]):hover
{
box-shadow: inset 0 0 0 1px #27496D, 0 5px 15px #193047;
}
.btn:not([disabled]):active
{
transform: translate(1px, 1px);
box-shadow: inset 0 0 0 1px #27496D, inset 0 5px 30px #193047;
}
.btn_yes
{
background-color: #6CBA30;
color: white;
}
.btn_no
{
background-color: #ED5B44;
color: white;
}
.btn_dark
{
background-color: #34495E;
color: white;
}
.btn_edit
{
background-color: #F27935;
color: white;
}
.btn_primary
{
background-color: #03A9F4;
color: white;
}
a
{
color: #008840;
}
input,
select
{
border: 1px solid #A9A9A9;
border-radius: 2px;
padding: 2px 4px;
}
svg
{
vertical-align: middle;
}
*[disabled]
{
opacity: 0.6;
cursor: not-allowed;
}
textarea
{
background-color: #FFFFE0;
}
input:valid
{
border: 1px solid #3EAF7C;
}
input:invalid
{
border: 1px solid #EC407A;
}
input:focus
{
outline: none;
border: 1px solid #3477C9;
}
input[type=date]
{
width: 8rem;
padding: 2px 0 2px 4px;
}
input[type=date]::-webkit-inner-spin-button,
input[type=date]::-webkit-clear-button,
input[type=date]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button
{
-webkit-appearance: none;
}
.vue-loading
{
position: absolute;
top: 0;
left: 0;
z-index: 120;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
border: none;
background-color: rgba(230, 233, 236, 0.8);
cursor: wait;
opacity: 0;
-o-transition: opacity 0.4s;
transition: opacity 0.4s;
display: -webkit-flex;
display: flex;
justify-content: center;
align-items: center;
}
.vue-loading > *
{
animation: rot 1.1s infinite linear;
}
@-webkit-keyframes rot
{
0%
{
transform: rotate(0deg);
}
100%
{
transform: rotate(359deg);
}
}
@-o-keyframes rot
{
0%
{
transform: rotate(0deg);
}
100%
{
transform: rotate(359deg);
}
}
@keyframes rot
{
0%
{
transform: rotate(0deg);
}
100%
{
transform: rotate(359deg);
}
}
#app
{
font-family: 'Avenir', Helvetica, Arial, sans-serif;
}
.login_modal
{
padding: 20px 25px;
}
.help_reset
{
color: #999;
padding-left: 1.85rem;
}
.home
{
height: 100vh;
overflow: hidden;
display: flex;
flex-direction: column;
}
.home_header
{
text-align: center;
background-color: #F27935;
color: white;
margin: 0;
padding: 0.8rem;
}
.home_learn
{
display: -webkit-flex;
display: flex;
-webkit-justify-content: center;
justify-content: center;
margin-top: 20px;
padding: 0 20px;
}
.home_link
{
display: inline-block;
text-align: center;
text-decoration: none;
text-transform: uppercase;
color: white;
background-color: #3EAF7C;
padding: 0.75rem 1.2rem;
margin: 1rem 1.5rem;
border-radius: 2rem;
letter-spacing: 0.85px;
}
.home_link:hover
{
box-shadow: inset 0 0 0 1px #46BD87, 0 3px 10px #193047;
}
.home_link:active
{
transform: translate(1px, 1px);
box-shadow: inset 0 0 0 1px #46BD87, inset 0 5px 12px #193047;
}
.home_body
{
flex: 1 1 auto;
display: flex;
justify-content: center;
align-items: center;
overflow: auto;
}
.login_panel
{
margin: 20px 25px;
}
@media screen and (max-width: 450px)
{
.home_learn
{
justify-content: space-around;
flex-wrap: wrap;
}
}
@media screen and (min-width: 480px)
{
.home_learn > * + *
{
margin-left: 60px;
}
}
.home_card
{
margin: 20px;
border-radius: 2px;
box-shadow:
0 2px 1px -1px rgba(0, 0, 0, 0.2),
0 1px 1px 0 rgba(0, 0, 0, 0.2),
0 1px 5px 0 rgba(0, 0, 0, 0.16);
transform-origin: 50% 0;
animation: form-fly-up 1.3s linear;
}
.home_card--header
{
line-height: 1.5;
margin: 0;
padding: 0 8px;
color: white;
background-color: #BA68C8;
text-align: center;
}
.home_card--body
{
position: relative;
overflow: hidden;
}
.button_bounce
{
animation: button-bounce 1s 0.12s linear;
}
.login_bar
{
display: flex;
justify-content: space-around;
margin: 25px 0;
}
.login_separator
{
display: flex;
}
.login_separator > div
{
flex: 1 1 100%;
padding: 0 8px;
}
@keyframes form-fly-up
{
0% { transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 500, 0, 1);
}
1.69% { transform: matrix3d(1, 0, 0, 0, 0, 1.351, 0, 0, 0, 0, 1, 0, 0, 330.533, 0, 1);
}
3.18% { transform: matrix3d(1, 0, 0, 0, 0, 1.431, 0, 0, 0, 0, 1, 0, 0, 209.854, 0, 1);
}
3.32% { transform: matrix3d(1, 0, 0, 0, 0, 1.431, 0, 0, 0, 0, 1, 0, 0, 200.398, 0, 1);
}
6.29% { transform: matrix3d(1, 0, 0, 0, 0, 1.306, 0, 0, 0, 0, 1, 0, 0, 52.745, 0, 1);
}
6.88% { transform: matrix3d(1, 0, 0, 0, 0, 1.27, 0, 0, 0, 0, 1, 0, 0, 35.081, 0, 1);
}
6.98% { transform: matrix3d(1, 0, 0, 0, 0, 1.263, 0, 0, 0, 0, 1, 0, 0, 32.413, 0, 1);
}
6.98% { transform: matrix3d(1, 0, 0, 0, 0, 1.263, 0, 0, 0, 0, 1, 0, 0, 32.23, 0, 1);
}
8.93% { transform: matrix3d(1.056, 0, 0, 0, 0, 1.101, 0, 0, 0, 0, 1, 0, 0, -4.194, 0, 1);
}
9.39% { transform: matrix3d(1.066, 0, 0, 0, 0, 1.07, 0, 0, 0, 0, 1, 0, 0, -9.217, 0, 1);
}
10.59% { transform: matrix3d(1.087, 0, 0, 0, 0, 1.005, 0, 0, 0, 0, 1, 0, 0, -17.779, 0, 1);
}
10.79% { transform: matrix3d(1.09, 0, 0, 0, 0, 0.996, 0, 0, 0, 0, 1, 0, 0, -18.669, 0, 1);
}
12.49% { transform: matrix3d(1.108, 0, 0, 0, 0, 0.94, 0, 0, 0, 0, 1, 0, 0, -21.678, 0, 1);
}
14.26% { transform: matrix3d(1.115, 0, 0, 0, 0, 0.91, 0, 0, 0, 0, 1, 0, 0, -19.497, 0, 1);
}
14.61% {transform: matrix3d(1.115, 0, 0, 0, 0, 0.907, 0, 0, 0, 0, 1, 0, 0, -18.72, 0, 1);
}
17.59% { transform: matrix3d(1.104, 0, 0, 0, 0, 0.906, 0, 0, 0, 0, 1, 0, 0, -11.021, 0, 1);
}
17.87% { transform: matrix3d(1.102, 0, 0, 0, 0, 0.908, 0, 0, 0, 0, 1, 0, 0, -10.337, 0, 1);
}
20.48% {transform: matrix3d(1.08, 0, 0, 0, 0, 0.928, 0, 0, 0, 0, 1, 0, 0, -4.9, 0, 1);
}
21.11% { transform: matrix3d(1.074, 0, 0, 0, 0, 0.933, 0, 0, 0, 0, 1, 0, 0, -3.919, 0, 1);
}
26.25% { transform: matrix3d(1.027, 0, 0, 0, 0, 0.978, 0, 0, 0, 0, 1, 0, 0, 0.127, 0, 1);
}
29.72% {transform: matrix3d(1.003, 0, 0, 0, 0, 0.998, 0, 0, 0, 0, 1, 0, 0, 0.518, 0, 1);
}
32.12% {transform: matrix3d(0.992, 0, 0, 0, 0, 1.007, 0, 0, 0, 0, 1, 0, 0, 0.432, 0, 1);
}
32.42% { transform: matrix3d(0.991, 0, 0, 0, 0, 1.008, 0, 0, 0, 0, 1, 0, 0, 0.414, 0, 1);
}
37.89% { transform: matrix3d(0.983, 0, 0, 0, 0, 1.014, 0, 0, 0, 0, 1, 0, 0, 0.11, 0, 1);
}
46.95% {transform: matrix3d(0.993, 0, 0, 0, 0, 1.006, 0, 0, 0, 0, 1, 0, 0, -0.012, 0, 1);
}
46.97% {transform: matrix3d(0.993, 0, 0, 0, 0, 1.006, 0, 0, 0, 0, 1, 0, 0, -0.012, 0, 1);
}
49.53% {transform: matrix3d(0.996, 0, 0, 0, 0, 1.003, 0, 0, 0, 0, 1, 0, 0, -0.01, 0, 1);
}
58.14% {transform: matrix3d(1.002, 0, 0, 0, 0, 0.998, 0, 0, 0, 0, 1, 0, 0, -0.001, 0, 1);
}
61.17% {transform: matrix3d(1.003, 0, 0, 0, 0, 0.998, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
}
64.17% {transform: matrix3d(1.002, 0, 0, 0, 0, 0.998, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
}
77.52% {transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
}
84.45% { transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
}
100% {transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
}
}
@keyframes button-bounce
{
0% {transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
}
2.1% { transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, -6.676, 0, 1);
}
4.1% { transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, -10.831, 0, 1);
}
8.21% {transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, -13.795, 0, 1);
}
11.41% { transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, -12.485, 0, 1);
}
14.51% {transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, -9.638, 0, 1);
}
20.72% {transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, -3.182, 0, 1);
}
27.03% { transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0.969, 0, 1);
}
33.23% { transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 2.063, 0, 1);
}
45.75% {transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0.472, 0, 1);
}
58.26% {transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, -0.309, 0, 1);
}
83.28% {transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0.046, 0, 1);
}
100% {transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
}
}
.form_field
{
margin: 8px;
}
.form_field > *
{
display: block;
}
.form_field > label
{
margin-bottom: 6px;
}
.field_error
{
font-family: 'Segoe UI', Tahoma, sans-serif;
font-size: 85%;
color: red;
margin: 3px 0;
}
.VuePassword
{
position: relative;
}
.VuePassword__Input
{
position: relative;
}
.VuePassword input
{
padding-right: 2.5em;
width: 100%;
}
.VuePassword__Toggle
{
color: gray;
display: inline-block;
height: 100%;
position: absolute;
right: 0;
top: 0;
z-index: 1;
cursor: pointer;
}
.VuePassword__Toggle__Icon
{
fill: currentColor;
height: 100%;
width: 1.5em;
margin-right: 0.5em;
user-select: none;
}
.VuePassword__Meter
{
color: rgb(175, 175, 175);
display: block;
height: 0.5rem;
margin-top: 0.2rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
width: 100%;
}
.VuePassword__Meter path
{
stroke: currentColor;
stroke-width: 2;
}
.VuePassword--very-weak
{
color: rgb(175, 175, 175);
}
.VuePassword--weak
{
color: rgb(230, 30, 30);
}
.VuePassword--medium
{
color: rgb(255, 160, 65);
}
.VuePassword--good
{
color: rgb(100, 200, 75);
}
.VuePassword--great
{
color: rgb(75, 150, 50);
}
.VuePassword__Message
{
cursor: default;
font-size: 1rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
text-align: right;
text-transform: uppercase;
}
</style>
</head>
<body>
<div id="app">
<div class="home">
<div>some text</div>
<div>some text</div>
<div>some text</div>
<div class="home_body">
<div class="home_card">
<h3 class="home_card--header">Reset password</h3>
<div class="home_card--body">
<form class="login_panel">
<h4>What is a good password ?</h4>
<ul>
<li>composed of multiple meaningless words</li>
<li>contains mixed-case letters</li>
<li>left + right padded with non-alphabet symbols</li>
<li>just make it longer – 20‐30 symbols and up</li>
</ul>
<div align="center">
<a class="home_link" href="https://www.grc.com/haystack.htm" target="_blank">TIPS + HINTS</a>
</div>
<div class="form_field">
<label for="inp5">Enter a new password</label>
<div class="VuePassword">
<div class="VuePassword__Input">
<input class="form-control" maxlength="100" required="required" type="password"> <a class="VuePassword__Toggle" role="button"><svg class="VuePassword__Toggle__Icon" viewbox="0 0 32 32">
<path d="M16 6c-6.979 0-13.028 4.064-16 10 2.972 5.936 9.021 10 16 10s13.027-4.064 16-10c-2.972-5.936-9.021-10-16-10zM23.889 11.303c1.88 1.199 3.473 2.805 4.67 4.697-1.197 1.891-2.79 3.498-4.67 4.697-2.362 1.507-5.090 2.303-7.889 2.303s-5.527-0.796-7.889-2.303c-1.88-1.199-3.473-2.805-4.67-4.697 1.197-1.891 2.79-3.498 4.67-4.697 0.122-0.078 0.246-0.154 0.371-0.228-0.311 0.854-0.482 1.776-0.482 2.737 0 4.418 3.582 8 8 8s8-3.582 8-8c0-0.962-0.17-1.883-0.482-2.737 0.124 0.074 0.248 0.15 0.371 0.228v0zM16 13c0 1.657-1.343 3-3 3s-3-1.343-3-3 1.343-3 3-3 3 1.343 3 3z"></path></svg> <!----></a>
</div><svg class="VuePassword__Meter" preserveaspectratio="none" viewbox="0 0 123 2">
<path class d="M0 1 L30 1"></path>
<path class d="M31 1 L61 1"></path>
<path class d="M62 1 L92 1"></path>
<path class d="M93 1 L123 1"></path></svg>
<div class="VuePassword__Message VuePassword--very-weak"></div>
</div>
</div>
<div class="form_field">
<label for="inp7">Retype the password</label> <input maxlength="100" required="required" style="width: 100%;" type="password">
<div class="field_error"></div>
</div>
<ul class="help_reset">
<li>password is case-sensitive</li>
<li>max length is 100 symbols</li>
<li>leading / trailing whitespace will be trimmed</li>
</ul>
<div class="login_bar">
<button class="btn btn_primary" type="submit">SUBMIT</button>
</div>
<div class="login_bar">
<button class="btn btn_dark" type="button">Back to Login</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</body></html>
如果有(即上述if语句为假),则只需添加新数量:
if (obj[item.equipment_type_id] == null)
下面是一个例子
obj[item.equipment_type_id].quantity += item.quantity;
答案 1 :(得分:0)
使用以下方法解决了此问题:
calcTotals(){
var groups = this.inspection.equipments.reduce(function(obj,item){
obj[item.equipment_type_id] = obj[item.equipment_type_id] || { equipment_type_id: item.equipment_type_id, total: 0};
// Calculate total based on action
var total = obj[item.equipment_type_id].total;
if(item.action === 'added'){
total = total + item.quantity;
}else{
total = total - item.quantity;
};
obj[item.equipment_type_id].total = total;
return obj;
}, {});
return groups;
}