Showing events on a multi room scheduler
$begingroup$
I write a web app that shows events on a multi room scheduler. I use VueJS for the first time on a real project.
Here, I loop through the events array every room column (two nested v-for). In jQuery I need to loop once through this array to fill all columns at once.
My question: is there any other more efficient way to write this code that fills rooms divs with events in Vue?
var vm = new Vue({
el: '#app',
data: {
rooms: [
{id: 1, title: 'Room 1' },
{id: 2, title: 'Room 2' }
],
events: [
{ id: 1, start: 230, duration: 30, title: 'Event 1', room_id: 2},
{ id: 2, start: 400, duration: 45, title: 'Event 2', room_id: 1}
]
}
}).agenda-wrapper { max-width: 100%; overflow-x: scroll; }
.agenda { padding-top: 50px; overflow: hidden; }
.room {
width:300px;
height:1170px;
padding: 0 10px;
margin-left: 5px;
background:#ECECEC;
position:relative;
float: left;
}
.room span {
position: absolute;
top: -20px;
height: 10px;
text-align: center;
width: 300px;
font-weight: bold;
}
.event {
display: block;
background:#fff;
color:#4B6EA8;
border:1px solid #ccc;
border-left:4px solid #c4183c;
position:absolute;
padding:0 10px;
font-weight:bold;
font-size:13px;
border-radius: 5px;
width: 280px;
}<div class="agenda-wrapper" id="app">
<div class="agenda" :style="{ width: (rooms.length * 350) + 'px' }">
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
v-for="event in events"
v-if="event.room_id === room.id">
<h5>{{ event.title }}</h5>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>javascript vue.js
$endgroup$
add a comment |
$begingroup$
I write a web app that shows events on a multi room scheduler. I use VueJS for the first time on a real project.
Here, I loop through the events array every room column (two nested v-for). In jQuery I need to loop once through this array to fill all columns at once.
My question: is there any other more efficient way to write this code that fills rooms divs with events in Vue?
var vm = new Vue({
el: '#app',
data: {
rooms: [
{id: 1, title: 'Room 1' },
{id: 2, title: 'Room 2' }
],
events: [
{ id: 1, start: 230, duration: 30, title: 'Event 1', room_id: 2},
{ id: 2, start: 400, duration: 45, title: 'Event 2', room_id: 1}
]
}
}).agenda-wrapper { max-width: 100%; overflow-x: scroll; }
.agenda { padding-top: 50px; overflow: hidden; }
.room {
width:300px;
height:1170px;
padding: 0 10px;
margin-left: 5px;
background:#ECECEC;
position:relative;
float: left;
}
.room span {
position: absolute;
top: -20px;
height: 10px;
text-align: center;
width: 300px;
font-weight: bold;
}
.event {
display: block;
background:#fff;
color:#4B6EA8;
border:1px solid #ccc;
border-left:4px solid #c4183c;
position:absolute;
padding:0 10px;
font-weight:bold;
font-size:13px;
border-radius: 5px;
width: 280px;
}<div class="agenda-wrapper" id="app">
<div class="agenda" :style="{ width: (rooms.length * 350) + 'px' }">
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
v-for="event in events"
v-if="event.room_id === room.id">
<h5>{{ event.title }}</h5>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>javascript vue.js
$endgroup$
$begingroup$
Hi and welcome to Code Review! I'm planning on answering your question later, but just out of curiousity: How would you do it in jQuery?
$endgroup$
– Simon Forsberg♦
Mar 5 at 8:44
$begingroup$
Hi, thank you for your reply! I think it would be something like that: '$.each(events, function(event){ var el = $("<div></div>").addClass("event").css({ "height": event.duration + "px", "top": event.start + "px" }).text(event.title); $('.room').data('place', event.place_id).append(el); });'
$endgroup$
– Alex
Mar 5 at 9:02
$begingroup$
I also think that maybe I need to do it on backend to make a rooms array look like that: { id: 1, title: 'Room 1', events: [{ id: 1, title: 'Event 1', start: 90, duration: 30 }] }
$endgroup$
– Alex
Mar 5 at 9:03
$begingroup$
Yes, backend is Laravel app. It has two models: Room and Event. Event belongsTo Room.
$endgroup$
– Alex
Mar 5 at 13:34
add a comment |
$begingroup$
I write a web app that shows events on a multi room scheduler. I use VueJS for the first time on a real project.
Here, I loop through the events array every room column (two nested v-for). In jQuery I need to loop once through this array to fill all columns at once.
My question: is there any other more efficient way to write this code that fills rooms divs with events in Vue?
var vm = new Vue({
el: '#app',
data: {
rooms: [
{id: 1, title: 'Room 1' },
{id: 2, title: 'Room 2' }
],
events: [
{ id: 1, start: 230, duration: 30, title: 'Event 1', room_id: 2},
{ id: 2, start: 400, duration: 45, title: 'Event 2', room_id: 1}
]
}
}).agenda-wrapper { max-width: 100%; overflow-x: scroll; }
.agenda { padding-top: 50px; overflow: hidden; }
.room {
width:300px;
height:1170px;
padding: 0 10px;
margin-left: 5px;
background:#ECECEC;
position:relative;
float: left;
}
.room span {
position: absolute;
top: -20px;
height: 10px;
text-align: center;
width: 300px;
font-weight: bold;
}
.event {
display: block;
background:#fff;
color:#4B6EA8;
border:1px solid #ccc;
border-left:4px solid #c4183c;
position:absolute;
padding:0 10px;
font-weight:bold;
font-size:13px;
border-radius: 5px;
width: 280px;
}<div class="agenda-wrapper" id="app">
<div class="agenda" :style="{ width: (rooms.length * 350) + 'px' }">
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
v-for="event in events"
v-if="event.room_id === room.id">
<h5>{{ event.title }}</h5>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>javascript vue.js
$endgroup$
I write a web app that shows events on a multi room scheduler. I use VueJS for the first time on a real project.
Here, I loop through the events array every room column (two nested v-for). In jQuery I need to loop once through this array to fill all columns at once.
My question: is there any other more efficient way to write this code that fills rooms divs with events in Vue?
var vm = new Vue({
el: '#app',
data: {
rooms: [
{id: 1, title: 'Room 1' },
{id: 2, title: 'Room 2' }
],
events: [
{ id: 1, start: 230, duration: 30, title: 'Event 1', room_id: 2},
{ id: 2, start: 400, duration: 45, title: 'Event 2', room_id: 1}
]
}
}).agenda-wrapper { max-width: 100%; overflow-x: scroll; }
.agenda { padding-top: 50px; overflow: hidden; }
.room {
width:300px;
height:1170px;
padding: 0 10px;
margin-left: 5px;
background:#ECECEC;
position:relative;
float: left;
}
.room span {
position: absolute;
top: -20px;
height: 10px;
text-align: center;
width: 300px;
font-weight: bold;
}
.event {
display: block;
background:#fff;
color:#4B6EA8;
border:1px solid #ccc;
border-left:4px solid #c4183c;
position:absolute;
padding:0 10px;
font-weight:bold;
font-size:13px;
border-radius: 5px;
width: 280px;
}<div class="agenda-wrapper" id="app">
<div class="agenda" :style="{ width: (rooms.length * 350) + 'px' }">
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
v-for="event in events"
v-if="event.room_id === room.id">
<h5>{{ event.title }}</h5>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>var vm = new Vue({
el: '#app',
data: {
rooms: [
{id: 1, title: 'Room 1' },
{id: 2, title: 'Room 2' }
],
events: [
{ id: 1, start: 230, duration: 30, title: 'Event 1', room_id: 2},
{ id: 2, start: 400, duration: 45, title: 'Event 2', room_id: 1}
]
}
}).agenda-wrapper { max-width: 100%; overflow-x: scroll; }
.agenda { padding-top: 50px; overflow: hidden; }
.room {
width:300px;
height:1170px;
padding: 0 10px;
margin-left: 5px;
background:#ECECEC;
position:relative;
float: left;
}
.room span {
position: absolute;
top: -20px;
height: 10px;
text-align: center;
width: 300px;
font-weight: bold;
}
.event {
display: block;
background:#fff;
color:#4B6EA8;
border:1px solid #ccc;
border-left:4px solid #c4183c;
position:absolute;
padding:0 10px;
font-weight:bold;
font-size:13px;
border-radius: 5px;
width: 280px;
}<div class="agenda-wrapper" id="app">
<div class="agenda" :style="{ width: (rooms.length * 350) + 'px' }">
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
v-for="event in events"
v-if="event.room_id === room.id">
<h5>{{ event.title }}</h5>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>var vm = new Vue({
el: '#app',
data: {
rooms: [
{id: 1, title: 'Room 1' },
{id: 2, title: 'Room 2' }
],
events: [
{ id: 1, start: 230, duration: 30, title: 'Event 1', room_id: 2},
{ id: 2, start: 400, duration: 45, title: 'Event 2', room_id: 1}
]
}
}).agenda-wrapper { max-width: 100%; overflow-x: scroll; }
.agenda { padding-top: 50px; overflow: hidden; }
.room {
width:300px;
height:1170px;
padding: 0 10px;
margin-left: 5px;
background:#ECECEC;
position:relative;
float: left;
}
.room span {
position: absolute;
top: -20px;
height: 10px;
text-align: center;
width: 300px;
font-weight: bold;
}
.event {
display: block;
background:#fff;
color:#4B6EA8;
border:1px solid #ccc;
border-left:4px solid #c4183c;
position:absolute;
padding:0 10px;
font-weight:bold;
font-size:13px;
border-radius: 5px;
width: 280px;
}<div class="agenda-wrapper" id="app">
<div class="agenda" :style="{ width: (rooms.length * 350) + 'px' }">
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
v-for="event in events"
v-if="event.room_id === room.id">
<h5>{{ event.title }}</h5>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>javascript vue.js
javascript vue.js
edited 2 hours ago
Simon Forsberg♦
48.7k7130286
48.7k7130286
asked Mar 5 at 8:26
AlexAlex
261
261
$begingroup$
Hi and welcome to Code Review! I'm planning on answering your question later, but just out of curiousity: How would you do it in jQuery?
$endgroup$
– Simon Forsberg♦
Mar 5 at 8:44
$begingroup$
Hi, thank you for your reply! I think it would be something like that: '$.each(events, function(event){ var el = $("<div></div>").addClass("event").css({ "height": event.duration + "px", "top": event.start + "px" }).text(event.title); $('.room').data('place', event.place_id).append(el); });'
$endgroup$
– Alex
Mar 5 at 9:02
$begingroup$
I also think that maybe I need to do it on backend to make a rooms array look like that: { id: 1, title: 'Room 1', events: [{ id: 1, title: 'Event 1', start: 90, duration: 30 }] }
$endgroup$
– Alex
Mar 5 at 9:03
$begingroup$
Yes, backend is Laravel app. It has two models: Room and Event. Event belongsTo Room.
$endgroup$
– Alex
Mar 5 at 13:34
add a comment |
$begingroup$
Hi and welcome to Code Review! I'm planning on answering your question later, but just out of curiousity: How would you do it in jQuery?
$endgroup$
– Simon Forsberg♦
Mar 5 at 8:44
$begingroup$
Hi, thank you for your reply! I think it would be something like that: '$.each(events, function(event){ var el = $("<div></div>").addClass("event").css({ "height": event.duration + "px", "top": event.start + "px" }).text(event.title); $('.room').data('place', event.place_id).append(el); });'
$endgroup$
– Alex
Mar 5 at 9:02
$begingroup$
I also think that maybe I need to do it on backend to make a rooms array look like that: { id: 1, title: 'Room 1', events: [{ id: 1, title: 'Event 1', start: 90, duration: 30 }] }
$endgroup$
– Alex
Mar 5 at 9:03
$begingroup$
Yes, backend is Laravel app. It has two models: Room and Event. Event belongsTo Room.
$endgroup$
– Alex
Mar 5 at 13:34
$begingroup$
Hi and welcome to Code Review! I'm planning on answering your question later, but just out of curiousity: How would you do it in jQuery?
$endgroup$
– Simon Forsberg♦
Mar 5 at 8:44
$begingroup$
Hi and welcome to Code Review! I'm planning on answering your question later, but just out of curiousity: How would you do it in jQuery?
$endgroup$
– Simon Forsberg♦
Mar 5 at 8:44
$begingroup$
Hi, thank you for your reply! I think it would be something like that: '$.each(events, function(event){ var el = $("<div></div>").addClass("event").css({ "height": event.duration + "px", "top": event.start + "px" }).text(event.title); $('.room').data('place', event.place_id).append(el); });'
$endgroup$
– Alex
Mar 5 at 9:02
$begingroup$
Hi, thank you for your reply! I think it would be something like that: '$.each(events, function(event){ var el = $("<div></div>").addClass("event").css({ "height": event.duration + "px", "top": event.start + "px" }).text(event.title); $('.room').data('place', event.place_id).append(el); });'
$endgroup$
– Alex
Mar 5 at 9:02
$begingroup$
I also think that maybe I need to do it on backend to make a rooms array look like that: { id: 1, title: 'Room 1', events: [{ id: 1, title: 'Event 1', start: 90, duration: 30 }] }
$endgroup$
– Alex
Mar 5 at 9:03
$begingroup$
I also think that maybe I need to do it on backend to make a rooms array look like that: { id: 1, title: 'Room 1', events: [{ id: 1, title: 'Event 1', start: 90, duration: 30 }] }
$endgroup$
– Alex
Mar 5 at 9:03
$begingroup$
Yes, backend is Laravel app. It has two models: Room and Event. Event belongsTo Room.
$endgroup$
– Alex
Mar 5 at 13:34
$begingroup$
Yes, backend is Laravel app. It has two models: Room and Event. Event belongsTo Room.
$endgroup$
– Alex
Mar 5 at 13:34
add a comment |
1 Answer
1
active
oldest
votes
$begingroup$
I asked you how you would do it in jQuery and you said that you would do something like:
$.each(events, function(event){
var el = $("<div></div>")
.addClass("event")
.css({ "height": event.duration + "px", "top": event.start + "px" })
.text(event.title);
$('.room').data('place', event.place_id).append(el);
});
And sure, this would only loop through the events array once. But what happens in every iteration? It does a jQuery search for $('.room').data('place', event.place_id), which is not a constant-time lookup operation, so this approach might be slower than what you think it is.
Now, for your Vue approach. You said:
maybe I need to do it on backend to make a rooms array look like that:
{ id: 1, title: 'Room 1', events: [{ id: 1, title: 'Event 1', start: 90, duration: 30 }] }
And yes, I agree with this. Putting the events inside your rooms makes much more sense.
As for your Vue template, overall the code looks fine. I'm not a CSS expert so I don't know if there's something you can improve there, but there probably is. Maybe consider using CSS Grids, where each room could be one column, and time-slots could be rows? The current approach of having 1px = 1 minute seems a bit unnatural to me.
As for this part:
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
v-for="event in events"
v-if="event.room_id === room.id">
<h5>{{ event.title }}</h5>
</div>
The only thing I would change is to put v-for and v-if before your :style-binding, as they are more important to be aware about, this is mostly my personal opinion though.
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
v-for="event in events"
v-if="event.room_id === room.id"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
>
<h5>{{ event.title }}</h5>
</div>
It would be nicer if your events would be inside the rooms, as then you could write:
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
v-for="event in room.events"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
>
<h5>{{ event.title }}</h5>
</div>
I would recommend in the future to use a Room component and a RoomEvent component so that you could write:
<Room v-for="room in rooms" :key="room.id" />
And the room-component:
<div class="room">
<span>{{ room.title }}</span>
<RoomEvent v-for="event in room.events" />
</div>
I think that the <h5>{{ event.title }}</h5> belongs inside the RoomEvent
Overall a nice job!
$endgroup$
$begingroup$
Thank you so much for such a great review! I rewrote backend as I mentioned. Now the code is a bit faster. As for CSS, I will look at CSS Grids one more time, but I'm afraid it's more complicated and less supportive by old browsers way. Anyway, thanks for your advice!
$endgroup$
– Alex
Mar 7 at 7:22
$begingroup$
Another small question: I have some plugins that need jQuery. Is it a good idea to use both jQuery (UI components like Select2) and Vue in same code?
$endgroup$
– Alex
Mar 7 at 7:24
$begingroup$
@Alex Yes unfortunately CSS Grids are not supported by older browsers. Regarding jQuery: I have never used it together with Vue myself but I would recommend to try to get rid of jQuery. There is probably Vue alternatives that you can use instead, if you are looking for UI-components then I can recommend Vuetify for example.
$endgroup$
– Simon Forsberg♦
Mar 7 at 12:05
$begingroup$
Thank you so much!
$endgroup$
– Alex
Mar 7 at 15:02
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214749%2fshowing-events-on-a-multi-room-scheduler%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
I asked you how you would do it in jQuery and you said that you would do something like:
$.each(events, function(event){
var el = $("<div></div>")
.addClass("event")
.css({ "height": event.duration + "px", "top": event.start + "px" })
.text(event.title);
$('.room').data('place', event.place_id).append(el);
});
And sure, this would only loop through the events array once. But what happens in every iteration? It does a jQuery search for $('.room').data('place', event.place_id), which is not a constant-time lookup operation, so this approach might be slower than what you think it is.
Now, for your Vue approach. You said:
maybe I need to do it on backend to make a rooms array look like that:
{ id: 1, title: 'Room 1', events: [{ id: 1, title: 'Event 1', start: 90, duration: 30 }] }
And yes, I agree with this. Putting the events inside your rooms makes much more sense.
As for your Vue template, overall the code looks fine. I'm not a CSS expert so I don't know if there's something you can improve there, but there probably is. Maybe consider using CSS Grids, where each room could be one column, and time-slots could be rows? The current approach of having 1px = 1 minute seems a bit unnatural to me.
As for this part:
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
v-for="event in events"
v-if="event.room_id === room.id">
<h5>{{ event.title }}</h5>
</div>
The only thing I would change is to put v-for and v-if before your :style-binding, as they are more important to be aware about, this is mostly my personal opinion though.
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
v-for="event in events"
v-if="event.room_id === room.id"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
>
<h5>{{ event.title }}</h5>
</div>
It would be nicer if your events would be inside the rooms, as then you could write:
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
v-for="event in room.events"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
>
<h5>{{ event.title }}</h5>
</div>
I would recommend in the future to use a Room component and a RoomEvent component so that you could write:
<Room v-for="room in rooms" :key="room.id" />
And the room-component:
<div class="room">
<span>{{ room.title }}</span>
<RoomEvent v-for="event in room.events" />
</div>
I think that the <h5>{{ event.title }}</h5> belongs inside the RoomEvent
Overall a nice job!
$endgroup$
$begingroup$
Thank you so much for such a great review! I rewrote backend as I mentioned. Now the code is a bit faster. As for CSS, I will look at CSS Grids one more time, but I'm afraid it's more complicated and less supportive by old browsers way. Anyway, thanks for your advice!
$endgroup$
– Alex
Mar 7 at 7:22
$begingroup$
Another small question: I have some plugins that need jQuery. Is it a good idea to use both jQuery (UI components like Select2) and Vue in same code?
$endgroup$
– Alex
Mar 7 at 7:24
$begingroup$
@Alex Yes unfortunately CSS Grids are not supported by older browsers. Regarding jQuery: I have never used it together with Vue myself but I would recommend to try to get rid of jQuery. There is probably Vue alternatives that you can use instead, if you are looking for UI-components then I can recommend Vuetify for example.
$endgroup$
– Simon Forsberg♦
Mar 7 at 12:05
$begingroup$
Thank you so much!
$endgroup$
– Alex
Mar 7 at 15:02
add a comment |
$begingroup$
I asked you how you would do it in jQuery and you said that you would do something like:
$.each(events, function(event){
var el = $("<div></div>")
.addClass("event")
.css({ "height": event.duration + "px", "top": event.start + "px" })
.text(event.title);
$('.room').data('place', event.place_id).append(el);
});
And sure, this would only loop through the events array once. But what happens in every iteration? It does a jQuery search for $('.room').data('place', event.place_id), which is not a constant-time lookup operation, so this approach might be slower than what you think it is.
Now, for your Vue approach. You said:
maybe I need to do it on backend to make a rooms array look like that:
{ id: 1, title: 'Room 1', events: [{ id: 1, title: 'Event 1', start: 90, duration: 30 }] }
And yes, I agree with this. Putting the events inside your rooms makes much more sense.
As for your Vue template, overall the code looks fine. I'm not a CSS expert so I don't know if there's something you can improve there, but there probably is. Maybe consider using CSS Grids, where each room could be one column, and time-slots could be rows? The current approach of having 1px = 1 minute seems a bit unnatural to me.
As for this part:
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
v-for="event in events"
v-if="event.room_id === room.id">
<h5>{{ event.title }}</h5>
</div>
The only thing I would change is to put v-for and v-if before your :style-binding, as they are more important to be aware about, this is mostly my personal opinion though.
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
v-for="event in events"
v-if="event.room_id === room.id"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
>
<h5>{{ event.title }}</h5>
</div>
It would be nicer if your events would be inside the rooms, as then you could write:
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
v-for="event in room.events"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
>
<h5>{{ event.title }}</h5>
</div>
I would recommend in the future to use a Room component and a RoomEvent component so that you could write:
<Room v-for="room in rooms" :key="room.id" />
And the room-component:
<div class="room">
<span>{{ room.title }}</span>
<RoomEvent v-for="event in room.events" />
</div>
I think that the <h5>{{ event.title }}</h5> belongs inside the RoomEvent
Overall a nice job!
$endgroup$
$begingroup$
Thank you so much for such a great review! I rewrote backend as I mentioned. Now the code is a bit faster. As for CSS, I will look at CSS Grids one more time, but I'm afraid it's more complicated and less supportive by old browsers way. Anyway, thanks for your advice!
$endgroup$
– Alex
Mar 7 at 7:22
$begingroup$
Another small question: I have some plugins that need jQuery. Is it a good idea to use both jQuery (UI components like Select2) and Vue in same code?
$endgroup$
– Alex
Mar 7 at 7:24
$begingroup$
@Alex Yes unfortunately CSS Grids are not supported by older browsers. Regarding jQuery: I have never used it together with Vue myself but I would recommend to try to get rid of jQuery. There is probably Vue alternatives that you can use instead, if you are looking for UI-components then I can recommend Vuetify for example.
$endgroup$
– Simon Forsberg♦
Mar 7 at 12:05
$begingroup$
Thank you so much!
$endgroup$
– Alex
Mar 7 at 15:02
add a comment |
$begingroup$
I asked you how you would do it in jQuery and you said that you would do something like:
$.each(events, function(event){
var el = $("<div></div>")
.addClass("event")
.css({ "height": event.duration + "px", "top": event.start + "px" })
.text(event.title);
$('.room').data('place', event.place_id).append(el);
});
And sure, this would only loop through the events array once. But what happens in every iteration? It does a jQuery search for $('.room').data('place', event.place_id), which is not a constant-time lookup operation, so this approach might be slower than what you think it is.
Now, for your Vue approach. You said:
maybe I need to do it on backend to make a rooms array look like that:
{ id: 1, title: 'Room 1', events: [{ id: 1, title: 'Event 1', start: 90, duration: 30 }] }
And yes, I agree with this. Putting the events inside your rooms makes much more sense.
As for your Vue template, overall the code looks fine. I'm not a CSS expert so I don't know if there's something you can improve there, but there probably is. Maybe consider using CSS Grids, where each room could be one column, and time-slots could be rows? The current approach of having 1px = 1 minute seems a bit unnatural to me.
As for this part:
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
v-for="event in events"
v-if="event.room_id === room.id">
<h5>{{ event.title }}</h5>
</div>
The only thing I would change is to put v-for and v-if before your :style-binding, as they are more important to be aware about, this is mostly my personal opinion though.
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
v-for="event in events"
v-if="event.room_id === room.id"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
>
<h5>{{ event.title }}</h5>
</div>
It would be nicer if your events would be inside the rooms, as then you could write:
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
v-for="event in room.events"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
>
<h5>{{ event.title }}</h5>
</div>
I would recommend in the future to use a Room component and a RoomEvent component so that you could write:
<Room v-for="room in rooms" :key="room.id" />
And the room-component:
<div class="room">
<span>{{ room.title }}</span>
<RoomEvent v-for="event in room.events" />
</div>
I think that the <h5>{{ event.title }}</h5> belongs inside the RoomEvent
Overall a nice job!
$endgroup$
I asked you how you would do it in jQuery and you said that you would do something like:
$.each(events, function(event){
var el = $("<div></div>")
.addClass("event")
.css({ "height": event.duration + "px", "top": event.start + "px" })
.text(event.title);
$('.room').data('place', event.place_id).append(el);
});
And sure, this would only loop through the events array once. But what happens in every iteration? It does a jQuery search for $('.room').data('place', event.place_id), which is not a constant-time lookup operation, so this approach might be slower than what you think it is.
Now, for your Vue approach. You said:
maybe I need to do it on backend to make a rooms array look like that:
{ id: 1, title: 'Room 1', events: [{ id: 1, title: 'Event 1', start: 90, duration: 30 }] }
And yes, I agree with this. Putting the events inside your rooms makes much more sense.
As for your Vue template, overall the code looks fine. I'm not a CSS expert so I don't know if there's something you can improve there, but there probably is. Maybe consider using CSS Grids, where each room could be one column, and time-slots could be rows? The current approach of having 1px = 1 minute seems a bit unnatural to me.
As for this part:
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
v-for="event in events"
v-if="event.room_id === room.id">
<h5>{{ event.title }}</h5>
</div>
The only thing I would change is to put v-for and v-if before your :style-binding, as they are more important to be aware about, this is mostly my personal opinion though.
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
v-for="event in events"
v-if="event.room_id === room.id"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
>
<h5>{{ event.title }}</h5>
</div>
It would be nicer if your events would be inside the rooms, as then you could write:
<div class="room" v-for="room in rooms" :key="room.id">
<span>{{ room.title }}</span>
<div class="event"
v-for="event in room.events"
:style="{ top: event.start + 'px', height: event.duration + 'px'}"
>
<h5>{{ event.title }}</h5>
</div>
I would recommend in the future to use a Room component and a RoomEvent component so that you could write:
<Room v-for="room in rooms" :key="room.id" />
And the room-component:
<div class="room">
<span>{{ room.title }}</span>
<RoomEvent v-for="event in room.events" />
</div>
I think that the <h5>{{ event.title }}</h5> belongs inside the RoomEvent
Overall a nice job!
answered Mar 5 at 22:40
Simon Forsberg♦Simon Forsberg
48.7k7130286
48.7k7130286
$begingroup$
Thank you so much for such a great review! I rewrote backend as I mentioned. Now the code is a bit faster. As for CSS, I will look at CSS Grids one more time, but I'm afraid it's more complicated and less supportive by old browsers way. Anyway, thanks for your advice!
$endgroup$
– Alex
Mar 7 at 7:22
$begingroup$
Another small question: I have some plugins that need jQuery. Is it a good idea to use both jQuery (UI components like Select2) and Vue in same code?
$endgroup$
– Alex
Mar 7 at 7:24
$begingroup$
@Alex Yes unfortunately CSS Grids are not supported by older browsers. Regarding jQuery: I have never used it together with Vue myself but I would recommend to try to get rid of jQuery. There is probably Vue alternatives that you can use instead, if you are looking for UI-components then I can recommend Vuetify for example.
$endgroup$
– Simon Forsberg♦
Mar 7 at 12:05
$begingroup$
Thank you so much!
$endgroup$
– Alex
Mar 7 at 15:02
add a comment |
$begingroup$
Thank you so much for such a great review! I rewrote backend as I mentioned. Now the code is a bit faster. As for CSS, I will look at CSS Grids one more time, but I'm afraid it's more complicated and less supportive by old browsers way. Anyway, thanks for your advice!
$endgroup$
– Alex
Mar 7 at 7:22
$begingroup$
Another small question: I have some plugins that need jQuery. Is it a good idea to use both jQuery (UI components like Select2) and Vue in same code?
$endgroup$
– Alex
Mar 7 at 7:24
$begingroup$
@Alex Yes unfortunately CSS Grids are not supported by older browsers. Regarding jQuery: I have never used it together with Vue myself but I would recommend to try to get rid of jQuery. There is probably Vue alternatives that you can use instead, if you are looking for UI-components then I can recommend Vuetify for example.
$endgroup$
– Simon Forsberg♦
Mar 7 at 12:05
$begingroup$
Thank you so much!
$endgroup$
– Alex
Mar 7 at 15:02
$begingroup$
Thank you so much for such a great review! I rewrote backend as I mentioned. Now the code is a bit faster. As for CSS, I will look at CSS Grids one more time, but I'm afraid it's more complicated and less supportive by old browsers way. Anyway, thanks for your advice!
$endgroup$
– Alex
Mar 7 at 7:22
$begingroup$
Thank you so much for such a great review! I rewrote backend as I mentioned. Now the code is a bit faster. As for CSS, I will look at CSS Grids one more time, but I'm afraid it's more complicated and less supportive by old browsers way. Anyway, thanks for your advice!
$endgroup$
– Alex
Mar 7 at 7:22
$begingroup$
Another small question: I have some plugins that need jQuery. Is it a good idea to use both jQuery (UI components like Select2) and Vue in same code?
$endgroup$
– Alex
Mar 7 at 7:24
$begingroup$
Another small question: I have some plugins that need jQuery. Is it a good idea to use both jQuery (UI components like Select2) and Vue in same code?
$endgroup$
– Alex
Mar 7 at 7:24
$begingroup$
@Alex Yes unfortunately CSS Grids are not supported by older browsers. Regarding jQuery: I have never used it together with Vue myself but I would recommend to try to get rid of jQuery. There is probably Vue alternatives that you can use instead, if you are looking for UI-components then I can recommend Vuetify for example.
$endgroup$
– Simon Forsberg♦
Mar 7 at 12:05
$begingroup$
@Alex Yes unfortunately CSS Grids are not supported by older browsers. Regarding jQuery: I have never used it together with Vue myself but I would recommend to try to get rid of jQuery. There is probably Vue alternatives that you can use instead, if you are looking for UI-components then I can recommend Vuetify for example.
$endgroup$
– Simon Forsberg♦
Mar 7 at 12:05
$begingroup$
Thank you so much!
$endgroup$
– Alex
Mar 7 at 15:02
$begingroup$
Thank you so much!
$endgroup$
– Alex
Mar 7 at 15:02
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214749%2fshowing-events-on-a-multi-room-scheduler%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
$begingroup$
Hi and welcome to Code Review! I'm planning on answering your question later, but just out of curiousity: How would you do it in jQuery?
$endgroup$
– Simon Forsberg♦
Mar 5 at 8:44
$begingroup$
Hi, thank you for your reply! I think it would be something like that: '$.each(events, function(event){ var el = $("<div></div>").addClass("event").css({ "height": event.duration + "px", "top": event.start + "px" }).text(event.title); $('.room').data('place', event.place_id).append(el); });'
$endgroup$
– Alex
Mar 5 at 9:02
$begingroup$
I also think that maybe I need to do it on backend to make a rooms array look like that: { id: 1, title: 'Room 1', events: [{ id: 1, title: 'Event 1', start: 90, duration: 30 }] }
$endgroup$
– Alex
Mar 5 at 9:03
$begingroup$
Yes, backend is Laravel app. It has two models: Room and Event. Event belongsTo Room.
$endgroup$
– Alex
Mar 5 at 13:34