I am looking to use flexbox and Vue.js to organize my sent messages in blue on the right and received messages in yellow on the left. How can I achieve this grouping effectively?

I've successfully built a messenger system using Vue.js with a Laravel backend. My goal is to display messages from myself (Jim, the logged in user) on the right side in blue and messages from Debbie (the recipient) on the left side in yellow, similar to Facebook or Twitter, utilizing flexbox:


https://i.sstatic.net/evYw2.png


Sample JSON Output

{
    "0": {
        "name": "Debbie",
        "message": "Good, Thanks for asking."
    },
    "1": {
        "name": "Jim",
        "message": "I'm good, how are you?"
    },
    "2": {
        "name": "Debbie",
        "message": "How are you?"
    },
    "3": {
        "name": "Jim",
        "message": "Hi Debbie"
    },
   "4": {
     "name": "Debbie",
     "message": "Hi Jim"
    }
}

To distinguish myself and my messages from others through the JSON API, what data should be sent? Is there a way to achieve this without altering the JSON output?

How can I integrate this layout into my existing messenger system built with flexbox? The main component being used is the conversation-messages component:

Vue.component('conversation-messages',{
      template: '#conversation-messages',
      props: ['conversationId'],
      data: function() {
        return {
          messages: [],
          url: ''
        }
      },
      mounted() {
        console.log("message mounted")
        this.getOldMessages(this.conversationId);
      },
});

View this question answered solely with CSS.

Implementing a Chat Bubble System Like FB Using CSS Tricks

Example HTML Structure with Floats Instead of Flexbox

<ul>
 <li class="him">By Other User</li>
 <li class="me">By this User, first message</li>
 <li class="me">By this User, second message</li>
 <li class="me">By this User, third message</li>
 <li class="me">By this User, fourth message</li>
</ul>

CSS Example Demonstrating Chat Bubbles Design

ul{
  list-style: none;
  margin: 0;
  padding: 0;
}

ul li{
  display:inline-block;
  clear: both;
  padding: 20px;
  border-radius: 30px;
  margin-bottom: 2px;
  font-family: Helvetica, Arial, sans-serif;
}

.him{
  background: #eee;
  float: left;
}

.me{
  float: right;
  background: #0084ff;
  color: #fff;
}

.him + .me{
  border-bottom-right-radius: 5px;
}

.me + .me{
  border-top-right-radius: 5px;
  border-bottom-right-radius: 5px;
}

.me:last-of-type {
  border-bottom-right-radius: 30px;
}

Answer №1

If you want to style the messages in a div, you can assign the class msgs using these defined rules:

tag:

<div v-for="message in messages" class="msgs">

style :

.msgs{
      display:flex;
      flex-direction:column;
      align-items:center;
      justify-content:space-between;
   }

To align each message based on whether it's yours or not, use conditional classes with v-if and v-else like this:

<div class="p-4 border-b"  v-if='message.name=="Jim"' :class="{me:message.name='Jim'}'>
      <p>{{message.message}}</p>
    </div>
    <div class="p-4 border-b" v-else :class="{him:true}">
      <p>{{message.message}}</p>
    </div>    

You can also use a data property called itSMe to detect the user's messages.

// Vue components and methods are set up here.
Vue.component('conversations',{
      template: '#conversations',
      data: function(){
        return{
          showConversation: false,
          conversationId: null
        }
      },

      // Methods for getting conversations
});

Vue.component('converstations-list',{
      // Template for displaying conversation list
});

Vue.component('conversation-messages',{
      // Template for displaying conversation messages
});

new Vue({
  el: '#app', // Initialize the Vue app
});
.border-b{
padding:0 10px;
}
.msgs{
  
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:space-between;
}
.me{
  align-self:flex-end;
  background: #0084ff;
  color: #fff;
}

.him{
  align-self:flex-start;
  background: #eee;
  float: left;
  border-radius: 20px 20px 20px 0;
}

// Additional styling options

.me {
  border-radius: 20px 0px 20px 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
      rel="stylesheet">

<!-- Include additional scripts and stylesheets -->

<div id="app">

  <conversations></conversations>

</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

POST requests in Angular Universal are making use of the IP address assigned to my server

My Angular Universal application (version 5.2.11) is currently hosted on Heroku, running on a Node server using express. I have implemented rate-limiters in all my POST routes to restrict requests by IP address, checking the request's IP through req.h ...

The Vuex function being mapped is not recognized as a function, yet it still manages to load correctly

Whenever I try to execute a mapped Vuex action inside the mounted hook, the action successfully runs but I encounter a "TypeError: xxx is not a function" message in the console. Below is the complete script section for this particular component: <sc ...

Connecting a Vue js model data to a Select2 select box

Utilizing select2 to improve an html select element, I am facing challenges in binding the value of the select element to a Vue variable because Select2 appears to be causing interference. Is there an optimal approach to achieve this data binding and even ...

Is it true that textarea is not compatible with AJAX .val() or .text() methods?

I'm attempting to utilize AJAX requests in order to transmit textarea data to a google form, however it appears that .val() isn't functioning correctly with textarea specifically. How can I resolve this issue? My goal is to enable individuals to ...

Merging the Select and Input elements side by side using Bootstrap grid system

Is there a way to combine all form group items like Select and Input using only the bootstrap framework? I attempted the method below, but there is an extra space between the Select and Input Box. Check out the DEMO ...

Using Jquery and the cookie.split method to extract and eliminate a value from a cookie

I am trying to figure out how to remove a specific matching value from a cookie using JavaScript. I have written a script that loops over the cookie and checks for matches, but I can't seem to successfully remove just the matching value. Any tips on a ...

Adjust the font size based on the dimensions of the container

I'm currently working on a script that dynamically sets the font-size based on the container's dimensions and the length of the text. This is what I have implemented so far. window.onload = function () { var defaultDimensions = 300; ...

An onClick event is triggered only after being clicked twice

It seems that the onClick event is not firing on the first click, but only works when clicked twice. The action this.props.PostLike(id) gets triggered with a delay of one click. How can I ensure it works correctly with just one click? The heart state togg ...

Ways to select a random row from a MySQL database

<button onclick="myUniqueFunction()">Press here!</button> <?php function myUniqueFunction() { $con = mysqli_connect("mysql.hostinger.no", "u452849516_altge", "password", "u452849516_altge"); $query = "S ...

Tips for querying orchestrate.io

Recently, I found myself in need of a user-friendly database for a small highscore system in my game development projects using JavaScript. Through the Github student developer pack, I came across Orchestrate.io. After discovering a suitable driver module ...

Retrieve vue environment variables within a template

I am trying to figure out how to access my environment variables directly from the template of Vue single file components. When attempting to do so like this: <img :src="`${process.env.VUE_APP_API_BASE_URL}/image/${image.filename}`" alt=" ...

What is the proper way to implement ref in typescript?

Currently, I am in the process of learning how to use Vue3 + Typescript. Previously, I have developed Vue2 applications using plain JavaScript. In my current project, I am attempting to define a reactive variable within the setup() function: setup() { ...

guiding user immediately to blog post upon successful login

I recently created a blog with a customized URL like instead of the traditional . Now, my dilemma is that I want to share this URL and have it redirect users to the login page if they are not logged in. Once they log in, I would like them to be redirect ...

I'm looking for a streamlined method to simultaneously access multiple APIs with GraphQL and React

For my client side project, I'm using GraphQL and React but opting not to use Redux for state management. Instead, I have organized my API calls into custom hook files as shown below: const [getSomeData, { data: getSomeDataData, loading: getSomeData ...

Node API is failing to insert user data into MongoDB

I'm currently developing a Restful API using Node.js and storing data in Mongodb, focusing on the user registration API. app.js apiRoutes.post('/signup', function(req, res) { if (!req.body.name || !req.body.password) { res.json({suc ...

Sticky positioning and outline effects

I have been working on creating a scrollable list with "sticky" headers. The functionality seems to be in place, but there are some visual glitches that I've encountered. The list itself is structured using a ul element styled with the Bootstrap 5 cl ...

Passing an anonymous function as a parameter to a function in ng-init is a common practice in AngularJS v1.4.8

Is it possible to save a call to an anonymous function using ng-init? For example: <div class="container-fluid" ng-app="AVF" ng-controller="ConfigController" ng-init="RegisterInitFunction(function() { $scope.GetData(); })" > In my controller: ...

JavaScript automatically arranges child elements within their parent container in a random distribution without any overlapping

I am experimenting with creating a dynamic layout of circles (divs with border-radius) within a container without any overlap. Check out my progress here - https://jsbin.com/domogivuse/2/edit?html,css,js,output var sizes = [200, 120, 500, 80, 145]; var m ...

Error encountered: "Unable to process Three.js FontLoader due to SyntaxError

I attempted to generate 3D text with FontLoader in Three.js, but encountered an error. My Three.js version is r99. const loader = new THREE.FontLoader(); //https://github.com/mrdoob/three.js/tree/dev/examples/fonts loader.load("./fonts/helvetiker_ ...

Exploring Vue 3 Composition API: Utilizing default Props and Incorporating DOM Operations within Lifecycle Methods

A Vue component is embedded within a NuxtJS application, utilizing the @nuxtjs/composition-api. Within this component, I have a <Link> component and my goal is to enhance the clarity of the code. In order to determine the color of my UiIcon comp ...