piljac1

piljac1

Full stack web developer at Tollé

Member Since 10 Months Ago

Mascouche

Experience Points
35,200
Total
Experience

4,800 experience to go until the next level!

In case you were wondering, you earn Laracasts experience when you:

  • Complete a lesson — 100pts
  • Create a forum thread — 50pts
  • Reply to a thread — 10pts
  • Leave a reply that is liked — 50pts
  • Receive a "Best Reply" award — 500pts
Lessons Completed
26
Lessons
Completed
Best Reply Awards
50
Best Reply
Awards
  • start your engines Created with Sketch.

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • first-thousand Created with Sketch.

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • 1-year Created with Sketch.

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • 2-years Created with Sketch.

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • 3-years Created with Sketch.

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • 4-years Created with Sketch.

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • 5-years Created with Sketch.

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • school-in-session Created with Sketch.

    School In Session

    Earned when at least one Laracasts series has been fully completed.

  • welcome-newcomer Created with Sketch.

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • full-time-student Created with Sketch.

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • pay-it-forward Created with Sketch.

    Pay It Forward

    Earned once you receive your first "Best Reply" award on the Laracasts forum.

  • subscriber Created with Sketch.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer Created with Sketch.

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • evangelist Created with Sketch.

    Laracasts Evangelist

    Earned if you share a link to Laracasts on social media. Please email [email protected] with your username and post URL to be awarded this badge.

  • chatty-cathy Created with Sketch.

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • lara-veteran Created with Sketch.

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • 10k-strong Created with Sketch.

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • lara-master Created with Sketch.

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • laracasts-tutor Created with Sketch.

    Laracasts Tutor

    Earned once your "Best Reply" award count is 100 or more.

  • laracasts-sensei Created with Sketch.

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • top-50 Created with Sketch.

    Top 50

    Earned once your experience points ranks in the top 50 of all Laracasts users.

Level 8
35,200 XP
Aug
08
1 day ago
Activity icon

Replied to Help Calling Information From Products Model

Your approach is bad performance wise. You're querying the database twice when you could call it once just by tweaking your where closes :

Product::orWhere([
    'slug' => 'Client-Licence',
    'slug' => 'Provider-License'
])->get();

// or a more "verbose" equivalent

Product::where('slug', 'Client-License')
    ->orWhere('slug', 'Provider-License')
    ->get();
Activity icon

Replied to [Alpine.js] Property Or Method "sidebarIsOpen" Is Not Defined On The Instance But Referenced During Render.

The problem is caused by @show which is a Vue reserved syntax. Hence, Vue is looking for a matching data property or a method. You could use x-on:click instead to avoid the issue.

However, I don't see why you would use Alpine in Vue components.

Activity icon

Awarded Best Reply on How Can I Make A Conditional Variable In PHP?

You can use the null coalescing operator that does what you want.

$AJAXproducts = $products ?? [];

It is a short for :

$AJAXproducts = isset($products) ? $products : [];
Activity icon

Replied to How Can I Make A Conditional Variable In PHP?

You can use the null coalescing operator that does what you want.

$AJAXproducts = $products ?? [];

It is a short for :

$AJAXproducts = isset($products) ? $products : [];
Aug
07
2 days ago
Activity icon

Replied to Override Nova Resource

On top of my head I see 3 possible solutions :

  • Use the Nova Hidden Field package to set an hidden input containing your type value

  • Create your own custom field which implements a hidden input

  • Last resort: Use a (nasty) little hack to inject your type in the request. To do so, create a "useless" validation rule on a field that will always be present in your create and update forms :

Text::make('Your field')
    ->rules(function($attribute, $value, $fail) use ($request) {
        $request->merge(['type' => 'holy_meal']);
    })
Aug
06
3 days ago
Activity icon

Awarded Best Reply on Vue Attributes Not Working, Like V-if And So On..

Your issue is due to multiple things :

  • In your Vue instantiation, you have a typo
const form = new Vue({
    el: '#form',
  
    components: { 
      ordercreatemodal,
    },
   
    data: { // Here you placed a comma instead of a colon
      showModal: false
    },
});
  • In your component, you have a defined method key with an object containing a showModal key. This is not causing any issue in your case because it is unused, but it is wrong for these reasons :

    1. It is completely useless for your use case
    2. The correct naming is methods and not method
    3. The methods object should only contain functions
    4. A function cannot have the same name as a prop or a data attribute
  • You're not using your showModal prop anywhere in your component. If you want to toggle the is-active on and off depending on your showModal prop, you can do the following :

<modal
  :class="{ 'is-active': showModal }"
  class="modal"
>
  • Your v-bind directive is not used correctly. You need to specify the prop's name.
<!-- Only using ":" is a shorthand for "v-bind:". Both are valid. -->
<order-create-modal :show-modal="showModal"></order-create-modal>
  • Your close and cancel buttons don't do anything. You cannot mutate a prop directly, so what you can do is emitting an event that can be caught and handled in the parent context :

Your component

<!-- Implement the same thing for the cancel button -->
<button
  class="modal-close is-large"
  aria-label="close"
  @click="$emit('close')"
></button>

Your view

<!-- Here you can capture the emitted "close" event to set the "showModal" attribute to false -->
<order-create-modal
  :show-modal="showModal"
  @close="showModal = false"
></order-create-modal>
Activity icon

Awarded Best Reply on How To Use @guest In The Vuejs Component

What @bobbybouwmann means is that you can pass auth()->get() as a prop to your component in your blade. You can use json_encode if you want to receive a boolean. Else, it will send an integer (which will also work, but depending on your prop validation, if you have any, it could throw errors).

In your blade file where you use your component

<nav-bar :is-guest="{{ json_encode(auth()->guest()) }}"></nav-bar>

In your component

<template>
  <div
    v-if="isGuest"
    class="navbar-guest"
  >
   
  </div>

  <div
    v-else
    class="navbar-auth"
  >
   
  </div
</template>

<script>
  export default {
    // This is the simplest props syntax, but you can implement prop validation if you'd like
    props: ['isGuest']
  }
</script>
Activity icon

Replied to How To Use @guest In The Vuejs Component

What @bobbybouwmann means is that you can pass auth()->get() as a prop to your component in your blade. You can use json_encode if you want to receive a boolean. Else, it will send an integer (which will also work, but depending on your prop validation, if you have any, it could throw errors).

In your blade file where you use your component

<nav-bar :is-guest="{{ json_encode(auth()->guest()) }}"></nav-bar>

In your component

<template>
  <div
    v-if="isGuest"
    class="navbar-guest"
  >
   
  </div>

  <div
    v-else
    class="navbar-auth"
  >
   
  </div
</template>

<script>
  export default {
    // This is the simplest props syntax, but you can implement prop validation if you'd like
    props: ['isGuest']
  }
</script>
Activity icon

Replied to Converting An Include From Laravel To Vue

Not sure what you have successfully translated to Vue, because you didn't post any Vue code, but for a dynamic @include equivalent, you could use dynamic components :

<template>
  <!-- ... -->
  <!-- As for props, I don't know what you need, so I'll let you manage them -->
  <component
    :is="getAppropriateComponent(question.type)"
    v-for="question in questions"
  />
  <!-- ... -->
</template>

<script>
  import ExampleComponent1 from './ExampleComponent1';
  import ExampleComponent2 from './ExampleComponent2';
  import ExampleComponent3 from './ExampleComponent3';

  export default {
    // ...
    components: {
      ExampleComponent1,
      ExampleComponent2,
      ExampleComponent3,
    }
    // ...
    methods: {
      getAppropriateComponent(type) {
        let component = 'ExampleComponent1';

        if (type == 2) {
          component = 'ExampleComponent2';
        } else if (type == 3) {
          component = 'ExampleComponent3';
        }

        return component;
      }
    }
  }
</script>

You can also manage props dynamically based on the question type (if you want to) :

<template>
  <!-- ... -->
  <!-- As for props, I don't know what you need, so I'll let you manage them -->
  <component
    :is="getAppropriateComponent(question.type)"
    v-for="question in questions"
    v-bind="getAppropriateProps(question.type)"
  />
  <!-- ... -->
</template>

<script>
  import ExampleComponent1 from './ExampleComponent1';
  import ExampleComponent2 from './ExampleComponent2';
  import ExampleComponent3 from './ExampleComponent3';

  export default {
    // ...
    components: {
      ExampleComponent1,
      ExampleComponent2,
      ExampleComponent3,
    }
    // ...
    methods: {
      getAppropriateComponent(type) {
        let component = 'ExampleComponent1';

        if (type == 2) {
          component = 'ExampleComponent2';
        } else if (type == 3) {
          component = 'ExampleComponent3';
        }

        return component;
      },
      
      getAppropriateProps(type) {
        let props = {
          props1: 'props1'
        };

        if (question.type == 2) {
          props = {
            props2: 'props2'
          };
        } else if (question.type == 3) {
          props = {
            props3: 'props3'
          };
        }

        return props;
      }
    }
  }
</script>
Activity icon

Replied to Regex

I think you're looking for something like this :

/\b(?=\w*a)(?=\w*b)(?=\w*c)\w+\b/g

Explanation :

  • \b → Marks the start of a word
  • (?=\w*a) → Check if there are 0 or more word characters followed by the letter "a" inside the word
  • (?=\w*b) → Check if there are 0 or more word characters followed by the letter "b" inside the word
  • (?=\w*c) → Check if there are 0 or more word characters followed by the letter "c" inside the word
  • \w+ → Capture the word respecting your conditions
  • \b → Marks the end of a word

P.S. A word character is anything alphanumeric or an underscore

Activity icon

Replied to Vue Axios Response Data Is Not Loading On Component In Laravel

@silencebringer Overwriting the entire variable content is not causing reactivity issues. What causes reactivity issues is updating the content of a key of the reactive array.

For example, this would not work without Vue.set or this.$set

this.articles[0] = 'new content';
Activity icon

Replied to Vue Attributes Not Working, Like V-if And So On..

Your issue is due to multiple things :

  • In your Vue instantiation, you have a typo
const form = new Vue({
    el: '#form',
  
    components: { 
      ordercreatemodal,
    },
   
    data: { // Here you placed a comma instead of a colon
      showModal: false
    },
});
  • In your component, you have a defined method key with an object containing a showModal key. This is not causing any issue in your case because it is unused, but it is wrong for these reasons :

    1. It is completely useless for your use case
    2. The correct naming is methods and not method
    3. The methods object should only contain functions
    4. A function cannot have the same name as a prop or a data attribute
  • You're not using your showModal prop anywhere in your component. If you want to toggle the is-active on and off depending on your showModal prop, you can do the following :

<modal
  :class="{ 'is-active': showModal }"
  class="modal"
>
  • Your v-bind directive is not used correctly. You need to specify the prop's name.
<!-- Only using ":" is a shorthand for "v-bind:". Both are valid. -->
<order-create-modal :show-modal="showModal"></order-create-modal>
  • Your close and cancel buttons don't do anything. You cannot mutate a prop directly, so what you can do is emitting an event that can be caught and handled in the parent context :

Your component

<!-- Implement the same thing for the cancel button -->
<button
  class="modal-close is-large"
  aria-label="close"
  @click="$emit('close')"
></button>

Your view

<!-- Here you can capture the emitted "close" event to set the "showModal" attribute to false -->
<order-create-modal
  :show-modal="showModal"
  @close="showModal = false"
></order-create-modal>
Aug
04
5 days ago
Activity icon

Replied to Check If A MorphMany Relationship Contains $post->id

All good, was about to check it out just now haha.

Activity icon

Awarded Best Reply on Check If A MorphMany Relationship Contains $post->id

You could do the following to solve your issue in a simplistic and reusable manner :

Post model

/**
 * Determine if the post has been liked by a specific user.
 *
 * @param  null|\App\User  $user
 * @return bool
 */
public function likedBy(?User $user)
{
    if (is_null($user)) {
        return false;
    }

    return $this->likes()->where('user_id', $user->id)->exists();
}

Wherever you need to check if a post was liked by a given user

$post->likedBy(auth()->user());

If you want to take it one step further you could also create a model (LikeableModel for example) extending the standard Model class and defining the likedBy method and the likes relationship. You could then extend your models that should be able to receive likes from the LikeableModel to make use of the same functionalities throughout all those models.

Activity icon

Replied to Check If A MorphMany Relationship Contains $post->id

Weird, I'll reproduce your "likes" architecture on my lunch break to see if I'm getting the same behavior.

Activity icon

Replied to Check If A MorphMany Relationship Contains $post->id

You could do the following to solve your issue in a simplistic and reusable manner :

Post model

/**
 * Determine if the post has been liked by a specific user.
 *
 * @param  null|\App\User  $user
 * @return bool
 */
public function likedBy(?User $user)
{
    if (is_null($user)) {
        return false;
    }

    return $this->likes()->where('user_id', $user->id)->exists();
}

Wherever you need to check if a post was liked by a given user

$post->likedBy(auth()->user());

If you want to take it one step further you could also create a model (LikeableModel for example) extending the standard Model class and defining the likedBy method and the likes relationship. You could then extend your models that should be able to receive likes from the LikeableModel to make use of the same functionalities throughout all those models.

Aug
03
6 days ago
Activity icon

Replied to [Vue Warn]: Error In V-on Handler: "SyntaxError: Unexpected Token , In JSON At Position 76"

You're missing double quotes around your string values.

But why don't you JSON.stringify a JavaScript object ? Way cleaner and safer to avoid "unexpected token" errors.

var tax_setting = JSON.stringify({
  total_tax_settings: {
    charge_tax: this.taxInfoRadioButton,
    tax_settings: [
      {
        tax_name: this.taxName,
        tax_rate: this.taxRate,
        tax_included_in_price: this.taxIncludeInPrice
      }
    ]
  }
});
Jul
31
1 week ago
Activity icon

Replied to Query Params In Vuejs

So I checked out Vue Router's documentation real quick, and for query params, you can use the following syntax (to pass query params to your defined route).

{
    path: '/home/video',
    name: 'videochat',
    component: VideoChat
}, 
<router-link :to="{ name: 'videochat', params: { usertype: yourUserType }}">Video chat</router-link>

And then, like @maverickchan said, you can use this.$route.query.usertype in your component to retrieve the value.

Activity icon

Replied to Query Params In Vuejs

@maverickchan Good to know !

Activity icon

Replied to Query Params In Vuejs

A: I'm not sure if there are special caveats for query params in Vue Router, as I've used it once and it was like a year ago in a Udemy course section, but the typical query param usage is wrong it your case. It should be :

'/home/video?usertype=usertypehere'

B: You can use the URLSearchParams interface inside a computed property :

userType() {
  // You can also define this in a data property inside the mounted lifecycle hook if you need to reuse it elsewhere
  let searchParams = new URLSearchParams(window.location.search);

  return searchParams.get('usertype');
},
Jul
30
1 week ago
Activity icon

Replied to When To Use Model Observers And Mutators

From the start, I'm not a big fan of setters and accessors for about the same reason as observers : it is a breeze while it lasts. However, when I'm talking about accessors, I'm not talking about those that act as computed values which don't "override" a column content.

For example :

// If you have a first_name column, I totally hate this
public function getFirstNameAttribute($value)
{
    return ucfirst($value);
}

// However, this is ok, as it doesn't alter any "original" column
public function getFullNameAttribute()
{
    return "{$this->first_name} {$this->last_name}";
}

When I access a model key representing a column name, I expect it to be as is. If however, I want a formatted version, I would define a computed accessor (if I may call them like that) that would explicitly say what it does.

That being said, it is still easier to manage than observers because you have access to methods like setRawAttribute and getRawAttribute. As for observers, you can only deactivate an observer's logic completely or not at all. You cannot disable a specific part of its code.

To answer your second question about repositories, most would tell you to use them for any logic communicating with the database. However, I would say that it depends, as sometime they can feel overkill (ex.: for small applications with a short life span and a few or no planned additional features). It is my opinion though and others can disagree on that point.

Activity icon

Replied to Displaying An Array

Your error messages explicitly say that you're trying to output an object instead of a string, which is not allowed.

Also, you can confirm this by reading the Youtube package's documentation :

// List videos in a given channel, return an array of PHP objects
$videoList = Youtube::listChannelVideos('UCk1SpWNzOs4MYmr0uICEntg', 40);

Try to dd($video); in your @foreach to find out how the object is built and what you need to output.

Then use it like that :

$video->yourKeyName;
Activity icon

Replied to Two Languages

@tray2 I personally use the first approach you mentioned with a tweak.

Let's say I have an item name, my website main language is fr and en is also supported, I will have a name column and a name_en column. The non-suffixed column represents the app default locale, which also acts as a fallback.

I also have a LocalizableModel class which extends Model and has one function, which is getLocalized. The function receives the non-suffixed column name as a param and tries to get the field in the current app locale. If the retrieved value is empty, fallback to the default local string.

$item->getLocalized('name')
Activity icon

Replied to When To Use Model Observers And Mutators

Honestly, the more is located in the model the better. It gives you way more control on your data than observers.

Observers can become a huge hassle in big scale applications, and I'm not speaking theoretically, I'm speaking from experience. It is easy to view observers as a go to for almost everything and it's a breeze when a small amount of code is present in them, but the more and more logic you add into them, the more you wish you've thought about your architecture earlier.

Don't get me wrong, they have useful use cases, such as handling denormalized data for example, but what you should think way before using an observer, is implementing events. I think the biggest error people make is to think of observers as globalized event dispatchers (ex.: if this condition is true when updating a model, send this notification). Most of the time, your notification should be sent, but then you start having cases where it shouldn't and that's when the absolute hell begins. So, USE EVENTS !!!

On another level of thought, Taylor Otwell (Laravel's creator) preaches for fat models, thin controllers. This is not answering your question directly, but what I want to point out is that you shouldn't be afraid to make your models fat (when appropriate of course).

Jul
29
1 week ago
Activity icon

Replied to Assign Same Value In The Vue Data Doesn't Change In The Dom

I don't know what's wrong on your side, but before posting my previous comment, I tested the behavior on CodePen. I just reproduced it and saved it for you.

https://codepen.io/jacob-pilon/pen/VweJWmM

Of course, you can see that I'm not using an Axios call, but I'm basically always reassigning the same values when changeAdminSettings is called. I set a watcher on the settings array which triggers an alert when updated. I did the same for the updated hook. Both ALWAYS get called when you focus out of the span (blur), which means an update is indeed caught and that the content has been re-rendered.

Activity icon

Replied to Laravel 5.8 Redirect()->route('name') Not Working

@Čamo Don't forget to mark @sergiu17's answer as best answer if it helped you fix your problem to mark your topic as resolved.

Activity icon

Replied to How To Change The Best Code?

You could create a class extending the package's class ?

Jul
28
1 week ago
Activity icon

Awarded Best Reply on How To Compile A Set Of Components Into Separate Files.

So, I tested the feature just now and it seems like it's working flawlessly. I don't know exactly what went wrong in your case, but here's what I've done :

  • Created a new Laravel project and ran npm install followed by npm install --save vue

  • Added the @babel/plugin-syntax-dynamic-import plugin to the webpack.mix.js file. Here's the full content of the file :

const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.babelConfig({
    plugins: ['@babel/plugin-syntax-dynamic-import'],
});

mix.js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css');

*Created a components folder under the resources folder and added ComponentA.vue and ComponentB.vue inside of it. Here's the content of the components (they're the same except that ComponentB has "ComponentB" written instead) :

<template>
  <div>
      Component A
  </div>
</template>
  • Registered components in resources/js/app.js with the dynamic imports syntax. Here are two alternatives that do the same (use one or another, not both), but I prefer the 1st one as it is more modular (less repetitive) :
import Vue from 'vue';

const components = {};

components.ComponentA = () => import(/* webpackChunkName: "component-a" */ '../components/ComponentA.vue');
components.ComponentB = () => import(/* webpackChunkName: "component-b" */ '../components/ComponentB.vue');

const app = new Vue({
    el: '#app',
    components
});
import Vue from 'vue';

const ComponentA = () => import(/* webpackChunkName: "component-a" */ '../components/ComponentA.vue');
const ComponentB = () => import(/* webpackChunkName: "component-b" */ '../components/ComponentB.vue');

const app = new Vue({
    el: '#app',
    components: {
        ComponentA,
        ComponentB
    }
});
  • Added the following code in the resources/views/welcome.blade.php file under the div containing the "Laravel" title
<div id="app">
    <component-a></component-a>
    <component-b></component-b>
</div>
  • Still in the resources/views/welcome.blade.php view, I also added the app.js script before the closing </body> tag :
<script src="{{ asset('js/app.js') }}"></script>
  • Ran npm run watch (you can run npm run dev for a one time compilation if you want)

Done !

Interesting fact (and clarification)

I've read multiple tutorials on how to implement dynamic imports and some of them wrapped page specific components in a if (document.getElementById('the_id')) statement, but I fiddled with both components (keeping only ComponentA in the welcome.blade.php view for example) and it seemed unnecessary to have any conditional structures since it was handled automatically (for Vue components at least).

To explain in a simpler way, if I only kept <component-a></component-a> in my blade view, the component-b.js chunk wasn't loaded and vice versa. If I kept both components, both chunks were loaded.

Activity icon

Awarded Best Reply on SCRIPT5018: SCRIPT5018: Unexpected Quantifier - Vuejs / Js

You could consume your entire pattern (including the filename= part) and use a capturing group around your .* to retrieve what's after filename=.

let stringToValidate = 'filename=whatever';

const matches = stringToValidate.match(/filename=(.*)/);

if (matches) {
  console.log(matches[1]);
  
  // Output: whatever
}
Activity icon

Replied to SCRIPT5018: SCRIPT5018: Unexpected Quantifier - Vuejs / Js

You could consume your entire pattern (including the filename= part) and use a capturing group around your .* to retrieve what's after filename=.

let stringToValidate = 'filename=whatever';

const matches = stringToValidate.match(/filename=(.*)/);

if (matches) {
  console.log(matches[1]);
  
  // Output: whatever
}
Activity icon

Replied to SCRIPT5018: SCRIPT5018: Unexpected Quantifier - Vuejs / Js

JavaScript RegEx lookbehinds are not supported in some browser versions and a lot of browsers don't support it, such as IE, Safari, Safari Mobile and more.

For more support info, visit this caniuse link.

Activity icon

Replied to How To Compile A Set Of Components Into Separate Files.

So, I tested the feature just now and it seems like it's working flawlessly. I don't know exactly what went wrong in your case, but here's what I've done :

  • Created a new Laravel project and ran npm install followed by npm install --save vue

  • Added the @babel/plugin-syntax-dynamic-import plugin to the webpack.mix.js file. Here's the full content of the file :

const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.babelConfig({
    plugins: ['@babel/plugin-syntax-dynamic-import'],
});

mix.js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css');

*Created a components folder under the resources folder and added ComponentA.vue and ComponentB.vue inside of it. Here's the content of the components (they're the same except that ComponentB has "ComponentB" written instead) :

<template>
  <div>
      Component A
  </div>
</template>
  • Registered components in resources/js/app.js with the dynamic imports syntax. Here are two alternatives that do the same (use one or another, not both), but I prefer the 1st one as it is more modular (less repetitive) :
import Vue from 'vue';

const components = {};

components.ComponentA = () => import(/* webpackChunkName: "component-a" */ '../components/ComponentA.vue');
components.ComponentB = () => import(/* webpackChunkName: "component-b" */ '../components/ComponentB.vue');

const app = new Vue({
    el: '#app',
    components
});
import Vue from 'vue';

const ComponentA = () => import(/* webpackChunkName: "component-a" */ '../components/ComponentA.vue');
const ComponentB = () => import(/* webpackChunkName: "component-b" */ '../components/ComponentB.vue');

const app = new Vue({
    el: '#app',
    components: {
        ComponentA,
        ComponentB
    }
});
  • Added the following code in the resources/views/welcome.blade.php file under the div containing the "Laravel" title
<div id="app">
    <component-a></component-a>
    <component-b></component-b>
</div>
  • Still in the resources/views/welcome.blade.php view, I also added the app.js script before the closing </body> tag :
<script src="{{ asset('js/app.js') }}"></script>
  • Ran npm run watch (you can run npm run dev for a one time compilation if you want)

Done !

Interesting fact (and clarification)

I've read multiple tutorials on how to implement dynamic imports and some of them wrapped page specific components in a if (document.getElementById('the_id')) statement, but I fiddled with both components (keeping only ComponentA in the welcome.blade.php view for example) and it seemed unnecessary to have any conditional structures since it was handled automatically (for Vue components at least).

To explain in a simpler way, if I only kept <component-a></component-a> in my blade view, the component-b.js chunk wasn't loaded and vice versa. If I kept both components, both chunks were loaded.

Jul
27
1 week ago
Activity icon

Replied to Evaluate The Result Of A Promise

You're right, in the case I posted above, you would always end up in the then function of submitForm no matter if saveForm catches an error or not. To solve that issue, you can return a promise reject within the catch function of saveForm. If there's no error in the post call, submitForm will hit then, else it will hit catch.

saveForm() {
    return axios.post('/post', data)
        .then(response => response.data)   // completed normally
	.catch(err) {
            console.log(err)
            return Promise.reject(err);
        }  // error 
},

submitForm() {
    this.saveForm()
        .then(response => {
            // do something if saving was successful
        })
        .catch(error => {
            // handle error
        })
}

Still no need of a new wrapping promise.

Activity icon

Replied to Assign Same Value In The Vue Data Doesn't Change In The Dom

It's never a good idea to modify the DOM directly when working with Vue. What you could do, is use this.$set on your current index and reassign the exact same object. That way, it will always trigger an update.

for (let i = 0; i < this.settings.length; i++) {
    if(this.settings[i].setting_name === response.data.setting_name) {
        this.settings[i].setting_value = response.data.setting_value;
        this.settings[i].setting_default_value = response.data.setting_default_value;
        this.$set(this.settings, i, this.settings[i]);
    }
}
Activity icon

Awarded Best Reply on Is There A Better Way To Do This?

Whoops my bad, posted too quickly, I meant associate. The attach function is for many to many relationships.

$rental->employee()->associate($u1);
$rental->save();
Activity icon

Replied to Is There A Better Way To Do This?

Whoops my bad, posted too quickly, I meant associate. The attach function is for many to many relationships.

$rental->employee()->associate($u1);
$rental->save();
Activity icon

Replied to Is There A Better Way To Do This?

Assuming your rental model does have an employee relationship, you could do :

$rental->employee()->attach($u1);
$rental->save();
Activity icon

Replied to Is There A Npm Package With V-if V-else Syntax For React-native?

You could use that syntax that is more readable than ternary imo (but doesn't work for "else" cases except if you use the same condition and invert it after) :

{condition &&
  <div>Hello!</div>
}

If the condition is true, it will output the content.

To answer your question "better", it is common for new React developers coming from Vue (v-if) and Angular (ng-if) to want something similar, but the closest you can get to that is by creating a HOC (higher order component) that works as a conditional wrapper. However, it would be considered bad practice because it hinders performance by adding an additional component which could be considered useless by the library standards.

Jul
26
2 weeks ago
Activity icon

Replied to How To Compile A Set Of Components Into Separate Files.

@mvnobrega I never explored it personally, but I'd like to test it out to find out if I can help you. I'll likely try later this evening or tomorrow, but I can't promise anything.

Activity icon

Replied to Assign Same Value In The Vue Data Doesn't Change In The Dom

@karlos545 His example uses the main VM, so you need to use data as an object key and not a function. In components, you need to use it as a function with a return statement as you posted.

Activity icon

Replied to Assign Same Value In The Vue Data Doesn't Change In The Dom

Not sure what you're trying to accomplish exactly, but two things are wrong with your code :

  1. Your method key should be called methods
  2. You're accessing and setting setting.change_setting_value and setting.setting_default_value while setting is not defined in your data properties.

A fixed version of what you posted would be :

const app = new Vue({
el: "#app",
data: {
    setting: {
        setting_default_value: "default value",
        change_setting_value: null
    }
},
methods: {
    changeSetting(evt) {
        if(evt.target.innerText === "") {
// dosen't change in the dom because setting_default_value never change its is the same value as before 
// now i want to know how can i change back the contenteditable span when i assign the same value
// i don't want to touch the dom 
            this.setting.setting_default_value = "default value" // not reflect in the dom what i can do to change the effect

// if i change the default value something else it will change in the dom in this case its the span element
            this.setting.setting_default_value = "change value" // reflect in the dom
        } else {
            this.setting.change_setting_value = "setting value has been change"
        }
    }
}
});

Now, as I said, I didn't understand what was the expected behavior, but with these fixes you'll get something functional.

Activity icon

Replied to How Hints Email Before Send Password Reset Link

If you're asking about how to format a partially hidden email address, this would work :

preg_replace('/(?<=.).([email protected])/', '*', '[email protected]');

// t**[email protected]

To explain the above RegEx, it translates to this : match any character that is preceded by any character and followed by at least 1 character and a @.

However if, you have two characters or less, it cannot match "in-between" characters, so [email protected] will remain entirely visible and [email protected] too. You can of course add additional logic to handle these cases (for example, split the @ and get the strlen of what is stored in the index 0, if anything).

Activity icon

Replied to Evaluate The Result Of A Promise

Just to specify even if it was marked as resolved, you can simply return the Axios call because it already returns a promise. No need for a wrapping promise, it just clutters the code and is totally useless in this specific use case.

saveForm() {
    return axios.post('/post', data)
        .then(response => response.data)   // completed normally
	.catch(err) { console.log(err) }  // error 
},

submitForm() {
    this.saveForm()
        .then(response => {
            // do something if saving was successful
        })
        .catch(error => {
            // handle error
        })
}
Jul
24
2 weeks ago
Activity icon

Replied to How To Compile A Set Of Components Into Separate Files.

What you're looking for is dynamic imports.

They basically work the same as the import statements, but instead of being compiled pre run time in the same big JS file, webpack creates chunks (JS files representing each dynamic imports) and you can then use dynamic logic to import them at runtime.

For example, you could do :

// Only load YourComponent when an element with the ID "whatever" is present on the page
if (document.getElementById('whatever')) {
  const YourComponent =
        () => import(/* webpackChunkName: "your-component" */ './components/YourComponent .vue');
}

The webpackChunkName represents the file name of the generated chunk (your-component.js).

You can find out more info on how to setup everything in this Laravel News article.

As stated in the Webpack doc linked below, dynamic imports use promises internally, so if you want to support older browsers such as IE, you should implement a promise polyfill.

Additional references :

Webpack doc : https://webpack.js.org/guides/code-splitting/#dynamic-imports

ECMAScript proposal : https://github.com/tc39/proposal-dynamic-import

Jul
22
2 weeks ago
Activity icon

Replied to Cannot Find Module "vue"

Wild guess, but maybe there's a conflict between mix and webpack ?

Laravel Mix is webpack with a wrapper around it, you do not need to install webpack.

Also, is vue listed in your node_modules folder ?

Jul
21
2 weeks ago
Activity icon

Awarded Best Reply on How To Do Calculation

You forgot your second number_format opening (number_format().

<td>RM{{ number_format(str_replace(',', '', $product->price), 2, '.', ',') - number_format(str_replace(',', '', $product->discount_amount), 2, '.', ',') }}</td>
Jul
20
2 weeks ago
Activity icon

Replied to How To Do Calculation

You forgot your second number_format opening (number_format().

<td>RM{{ number_format(str_replace(',', '', $product->price), 2, '.', ',') - number_format(str_replace(',', '', $product->discount_amount), 2, '.', ',') }}</td>
Activity icon

Replied to How To Access Index-name .env Var With Algolia Process.env.MIX_VUE_APP_INDEX_NAME;

I didn't understand your comment quite well, some code would probably help. Also I looked at your original code blocks again and your props object should be outside of your data function :

export default {
  props: {
    job: Object,
    imageUrl: String
  },

  data() {
    return {
      searchClient: algoliasearch(process.env.MIX_ALGOLIA_APP_ID, process.env.MIX_ALGOLIA_SEARCH),
      indexName: process.env.MIX_VUE_APP_INDEX_NAME
    }
  }
};
Activity icon

Awarded Best Reply on Get Distinct Associative Arrays Based On Matching Value Pairs

Assuming your messages are already sorted by startedAt, this would work with some tweaks because this is just sandbox code. Functions would be private in a controller or model class (changes would be needed to adapt the logic to the Message model) and would then be prefixed with $this->.

<?php

function sameSenderAndReceiverPairFound($message, $pair) {
    return $message['from'] === $message['to']
        && $pair[0] === $message['from']
        && $pair[1] === $message['from'];
}

function differentSenderAndReceiverPairFound($message, $pair) {
    return $message['from'] !== $message['to']
        && in_array($message['from'], $pair)
        && in_array($message['to'], $pair);
}

function pairFound($message, $pair) {
    return sameSenderAndReceiverPairFound($message, $pair)
        || differentSenderAndReceiverPairFound($message, $pair);
}

$messages = [
    '-MC1kTfrrDHY3ZbidJ4Q' => [
        'from' => 'lSUfZ4sgEJd',
        'message' => 'test message four no more!',
        'startedAt' => '2020-07-12 11:21:10',
        'to' => 'CWgPqdn3YweN'
    ],
    '-MC09BsjtXP0izITsThf' => [
        'from' => 'CWgPqdn3YweN',
        'message' => 'test message three',
        'startedAt' => '2020-07-11 11:20:19',
        'subject' => '-MC00BHCZlXUp25C5nlS',
        'to' => 'lSUfZ4sgEJd'
    ],
    '-MC1kAi1niswXtjY_h4s' => [
        'from' => 'CWgPqdn3YweN',
        'message' => 'test message two',
        'startedAt' => '2020-07-12 11:19:52',
        'to' => 'lSUfZ4sgEJd'
    ],
    '-MC1kOtfnIlAYtmJsD' => [
        'from' => 'CWgPqdn3YweN',
        'message' => 'test message one',
        'startedAt' => '2020-07-12 11:18:50',
        'to' => 'lSUfZ4sgEJd'
    ],
    '-MC1kOtfnIlAhgcufu' => [
        'from' => 'CWgPqdn3YweN',
        'message' => 'test message zero',
        'startedAt' => '2020-07-12 11:00:50',
        'to' => 'YLisXjk07w93'
    ]
];

$idPairs = [];

foreach ($messages as $key => $message) {
    $pairFound = false;
    
    foreach ($idPairs as $pair) {
        if (pairFound($message, $pair)) {
            $pairFound = true;
            break;
        }
    }
    
    if ($pairFound) {
        unset($messages[$key]);
    } else {
        $idPairs[] = [$message['from'], $message['to']];
    }
}

However, performance wise, I don't recommend processing this kind of logic with PHP. I would translate the above logic in a custom SQL query which would speed up the process for a big dataset.

Still, I don't think your current architecture is the best possible for what you're trying to accomplish. Why aren't your messages associated to a conversation ? This would facilitate your SQL query by a lot.

Another step you could take to increase the performance would be a small database denormalization. Of course, in school you're being yelled at if your database is not normalized correctly, but truth is, in real life, some appropriate denormalizations are worth it to gain an incredible amount of performance. For example, in your case, you would have a conversations database table which would contain a last_message_sent_at column. This column would be kept up to date via an observer (MessageObserver). Having that kind of data accessible at the first level of your query (no join necessary) and without any sorting logic necessary makes a huge difference regarding query speed.

Activity icon

Replied to JSON Parse Error - Vue

I think you issue wasn't that your logic was all in mounted. JavaScript is asynchronous, so I'm pretty sure that once your code reached report.load(this.definition), your definition data property wasn't set yet (awaiting for the response). Something along those lines would probably have worked :

axios.get('/reports/view/1')
  .then(({ data }) => this.definition = data.report.definition)
  .then(() => {
    var viewer = new window.Stimulsoft.Viewer.StiViewer(null, 'StiViewer', false);
    
    var report = new window.Stimulsoft.Report.StiReport();

    report.load(this.definition);

    viewer.report = report;

    viewer.renderHtml('viewer');
  });