nolros

nolros

Member Since 6 Years Ago

Experience Points
96,450
Total
Experience

3,550 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
422
Lessons
Completed
Best Reply Awards
35
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 20
96,450 XP
May
09
3 months ago
Activity icon

Replied to Laravel File Upload With Auth User

@lmao3d that is a very big question. Suggest you look at documentation and try and then post when you run into issues, but as a starting point. There are a number of approaches in your controller. Use auth in each controller method or the right way middleware - both are ok if you are starting out.


  public function saveImage(Request $request)
  {
    if (auth()->check()) {
      if ($request->has("image")) {
        $image = $request->image;
        return $image->storeAs('images', $image->getClientOriginalExtension());
      }
    }

    return response()->json(['Unauthorized']);
  }

  public function viewImage($id)
  {
    if (auth()->check()) {
      $image = Image::find($id);
      return view('dashboard.main')->with(['image' => $image]);
    }

    return response()->json(['Unauthorized']);
  }



// OR Middlewar

  public function __construct()
  {
    $this->middleware('auth');
  }

  public function viewImage(Request $request)
  {
    if ($request->has("image")) {
      $image = $request->image;
      return $image->storeAs('images', $image->getClientOriginalExtension());
    }
  }

  public function viewImage($id)
  {
      return view('dashboard.main')->with(['image' => Image::find($id)]);
  }

Activity icon

Replied to Uploading Img Error

@mokrani building on Snapey reply. Try this code. Laravel has a StoreAs helper for storage. storeAs method, which accepts the path, file name, and disk name as its arguments. We will just path images and filename as you format


  public function uploadimage(Request $request)
  {
    // removing validation for brevity sake
    if ($request->has("input_img")) {
      $image = $request->input_img;
      return $image->storeAs('images', (time().'.'.$image->getClientOriginalExtension())) 
        ? "Image Upload successfully"
        : "Oops something went wrong";
    }
  }

May
06
3 months ago
Activity icon

Awarded Best Reply on ToSearchableArray Limiting Data Send With Eloquent Relationship

Another approach would as follows where you can access the relationship

public function toSearchableArray()
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'shows' => $this->showsSelect()
        ];
    }


// relationship with select
public function showsSelect()
    {
        return $this->hasMany(Show::class)->select('id','event_id','date');
    }

// standard relationship
public function shows()
    {
        return $this->hasMany(Show::class);
    }

Activity icon

Replied to ToSearchableArray Limiting Data Send With Eloquent Relationship

Another approach would as follows where you can access the relationship

public function toSearchableArray()
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'shows' => $this->showsSelect()
        ];
    }


// relationship with select
public function showsSelect()
    {
        return $this->hasMany(Show::class)->select('id','event_id','date');
    }

// standard relationship
public function shows()
    {
        return $this->hasMany(Show::class);
    }

Activity icon

Replied to ToSearchableArray Limiting Data Send With Eloquent Relationship

you cannot use eager loading like that. If you want to do it that way then try lazy loading and replace "with" with "load".


 public function toSearchableArray()
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'shows' => $this->load(['show' => function($query) {
                $query->select('id','event_id','date'); // select of show
              }]),
        ];
    }
Activity icon

Replied to How To Prevent Multiple Form Submits For Two Submit Buttons

@noblemfd use event.stopPropagation(); as it stops the event propagating. event. preventDefault() will stop the submit button from acting like a submit button and only work on the event.

$("span").click(function(event){
  event.stopPropagation();
  event. preventDefault();

  alert("The span element was clicked.");
});

Activity icon

Replied to Relation Only Return On Dd()

@vafa the Rideable is not an object, you most likely returned an array or json. Go look at how you are returning Rideable in the view

Activity icon

Replied to Which Is The Best Method To Update The Value Of The Fields Created_by And Updated_by

@ajithlal in your Model or Controller. That said, Laravel automatically timestamps you inserts if you have $timestamps = true in your model and you have $timestamps in your migration.

Activity icon

Replied to ToSearchableArray Limiting Data Send With Eloquent Relationship

@chrisgrim here you go. You use select() to select the columns. There are other ways, but stick with select. Dont forget to include the event->show relationship column in your select, example, if show is related by event_id, then add that in your show select, without it you wont get show data

  public function getById($id)
  {
    return Event::where('id',$id)
            ->with(['show' => function($query) {
                $query->select('id','event_id','date'); // select of show
              }])
            ->select('id','name') // select of event
            ->first();
  }

Activity icon

Replied to No Data Are Created In Created_at/updated_at Timestamps While Inserting/updating

@_jay do you have timestamps set to true in your model >

<?php

namespace App\MatrixMe;

use Illuminate\Database\Eloquent\Model;


class Example extends Model
{

  /**
   * Indicates if the model should be timestamped.
   *
   * @var bool
   */
  public $timestamps = true;

}


Activity icon

Replied to Delete String Contains <img>

@mmuqiitf @michaloravec answer is exactly right.

Activity icon

Replied to Vue Component Not Displaying In Laravel

@cridev it is most likely looking for bootstrap.js from the bootstrap CSS framework. Don't copy the bootstrap.js from JS to public - leave that boostrap where it is i.e. in teh same folder as app.js.

Just run npm install bootstrap from command line and it should work fine.

https://getbootstrap.com/docs/4.4/getting-started/download/#npm

Activity icon

Replied to Simplest Way To Convert "Zulu" Time With Carbon And Laravel?

@moprocto try this.

$timestamp = '1998-05-04T23:16:01.000+00:00';
$date = Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->setTimezone('UTC');

Activity icon

Replied to Delete String Contains <img>

@mmuqiitf paste some code as it is difficult to grasp what you attempting to do. You can remove img tags or other tags with JavaScript, but again maybe some more context will help.

Activity icon

Replied to Php Returning Empty Array?

@pt-83 try this

    <ul>
      <?php foreach ($person as $key => $feature): ?>
        <li><strong><?php $key; ?></strong> <?php $feature; ?></li>
      <?php endforeach; ?>
    </ul>

Activity icon

Replied to Images Store Cannot Found

Assuming it is stored in public/image and NOT public/images then just add relative prefix i.e. '/' without that you will run into problems. You might need "../" so test for both

<img src="{{ '/' . $image->path}}"/> 

Activity icon

Replied to SEO For Blog

@davy_yg a great question, but not a simple answer. You need to have meta data, but you also need other semantic data such OpenGraph, Twitter Cards. For example, if you run your URL through https://gtmetrix.com/ you will get pagespeed as well as a ton of SEO related info and measurements e.g. JavaScript, Images, etc. A good site like ours scores almost perfect https://www.cmosolution.com . Also, there are blog / article snippets for SERP placement, etc. https://developers.google.com/search/docs/data-types/article It takes a lot to truly optimize blog / site . That said, the most important part of SEO is 1. # of backlinks to your posts and 2 quality and frequency of content. Good content drives traffic and traffic results in backlinks and rankings. Final point, ranking on intent or phrases is a difficult at best. Try find a very specialized niche and then look to own a SERP in that niche.

Activity icon

Replied to Create A Record With HasMany

You can do this

return $user->invoice()->create([...]);


// this is accessing the invoice data on the relationship
$user->invoice

/// this is the invoice model and as such you can run the model method
$user->invoice()

Activity icon

Replied to Design Strategies, Front End Dynamic Add Form Fields

Laravel is ok for form creation and submission, and there is a lot you can do in terms of conditions, etc. but it s not dynamic and for that you would need JavaScript or a foundation like Vue. For example, Laravel / PHP has no client event handling so mouse events, etc would impossible. As far as dynamic forms i.e. form 1 - part 1 and then form 1 - part 2 --- again you could do it with Laravel, but it would be ugly and you would have your work cutout, for example, if the user wanted t go back from part 2 to part 1, you would need to maintain data / state in session or something. In that case I would almost always use JS / Vue. Take a look at Vue-form .. really ease to use.

Activity icon

Replied to Realtime Fetching Data

Bobby is right on. Need to use Websockets as polling a server is never good. Using websockets will observe data on the server ad then notify your server client that something has changed. Traditional client server approach would be highly inefficient with 99% of HTTP traffic pointless. Look at Pusher as they have great JS and Laravel integration, API’s and tutorials.

That said, if you have no choice then you can use something like this that I use for polling an endpoint for a response, but I use this for a short period or if the response window is variable.



// ./utils/client-fetch.js
export default async function fetchData(endpoint) {
  const {data} = await fetch(endpoint);
  return data;
}

// ./utils/api.js
import Vue from "vue";
// A simple wrapper around the native
// `fetch()` function.
import fetchData from "./client-fetch";

const ENDPOINTS = {
  get dashboard() {
    return `https://api/v1/dashboard`
  }
};

async function withPolling(callback, interval) {
  const data = await callback();
  // If no polling interval is given we return object
  if (!interval) return { data };
  // Otherwise, we create a new `Vue.observable` or Observable in JS and begin polling
  const observableData = Vue.observable({ data });
  const poll = () => {
    setTimeout(async () => {
      observableData.data = { ...(await callback()) };
      poll();
    }, interval);
  };
  poll();

  return observableData;
}

export default function api({ endpoint, interval }) {
  return withPolling(() => fetchData(ENDPOINTS[endpoint]), interval);
}

// ./services/dashboard.js
import api from "../utils/api";

export default {
  dashboard: () => api({ endpoint: "dashboard", interval: 2000 })
};


// ./App.vue component
<template>
</template>

<script>
import dashboardService from "./services/dashboard";

export default {
  name: "App",
  data() {
    return {
      dashboardResponse: { data: {} }
    };
  },
  async created() {
    this.dashboardResponse = await dashboardService.dashboard();
  }
};
</script>

Activity icon

Replied to Product With Order Model Relation.

Although I understand what you attempting to do, you cannot paginate on a collection of a collection. You can get a product and paginate orders on a product, but given the way pagination works it wouldn't make sense. The right way to do it is to get products. List out products and when the user selects a product then get a collection of orders which can be paginated so you can paginate products and then when a product is selected get orders for that product and paginate those orders but you cannot get a collection and for each item get a pagination. When you see what is returned it will make sense.

Activity icon

Replied to Redirecting To Front End With Passport Personal Access Token

Assuming you are receiving the token it will be in SESSION storage. Assuming that is the key then you will get it from session with $value = session()->get('token') then you then tou can return redirect()->with(['token_social' => $value])

Activity icon

Replied to Laravel Login Errror Messages For AJAX

Best way to troubleshoot ajax response is to open your developer tool console on your browser. Go to to network tab, reload if necessary, find the response from the server and click on that to open it, then lick on response to see any errors and a trace of the errors. It will given you a trace of the error flow. 422 is normally validation or you have a route issue, most likely, POST action but the route is action is set to GET. Go check your route to ensure that it is setup for POST is you are POSTing.

Activity icon

Replied to Sactrum Strategy To Not Redirect To The Login Screen (SPA).

You would need to use Vue Router. For smaller apps you can can manually add it as such

  1. in your route you would add a router meta tag i.e. meta: { requiresAuth: true } . Example, in user path below
  2. You then add the router.beforeEach((to, from, next) logic below which will look for the meta tag and route to login

NOTE: this assumes you have auth setup with Sanctum or JWT i.e. I'm looking for the user state in the store. If it is set then we proceed to next()


import Vue from "vue";
import Router from "vue-router";
import store from "@/store";
Vue.use(Router);

const router = new Router({
  mode: "history",
  routes: [
    {
      path: "/user",
      name: "user",
      component: () =>import(./views/User.vue"),
      meta: { requiresAuth: true }
    },
    {
      path: "/login",
      name: "login",
      component: () =>import(./views/Login.vue"),
    },
  ]
});

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    if (!store.user) {
      next({
        name: "login",
        query: { redirect: to.fullPath }
      });
    } else {
      next();
    }
  } else {
    next();
  }
});

export default router;

May
05
3 months ago
Activity icon

Commented on Rapid Code Generation With Blueprint

@jason-mccreary I accidentally stumbled across this gem! holy ****! Nice work! It has incredible potential to be expanded in JavaScript / Vue / Auth and the list goes on ... awesome!

Activity icon

Commented on Refactoring To Lookup Tables

@caleb do you have a blog || site || education site, where you publish these types of nuggets?

May
04
3 months ago
Activity icon

Commented on How We Compare With "The Real" AlpineJS

Very cool! thank you! You should create your own education series. You have a gift for explaining complex concepts.

Apr
27
3 months ago
Activity icon

Replied to Linking A JSON Object To JavaScript Comparison And Logical Operators

Sounds like a cut and paste from a homework assignment

Apr
17
3 months ago
Activity icon

Replied to Inherit Trait In Blade View

@bvanhaastrecht you cannot inject a trait. You need to create a class and you can then add the trait to the trait to that class,

Activity icon

Replied to VUEX State Variables Default

@apollobln lots wrong in what you've done there. Let me try use a specific example.

Here is an example component with all 3 requests in a Promise all. Once all 3 resolve loading will be true and it will render each data. Note that if any one of them fails then all 3 fail in a promise all. You dont need to do a promise all. You could fetch them individually. Also, in this example I'm just using promises no await async.

<template>
    <div class="flex flex-wrap">
        <div v-if="loading">
            <ul>
                <li v-for="(feed, idxv) in getFeeds"
                    :key="idxv">
                </li>
            </ul>
            <ul>
                <li v-for="(expert, idxe) in getExperts"
                    :key="idxe">
                </li>
            </ul>
            <ul>
                <li v-for="(post, idxp) in getPosts"
                    :key="idxp">
                </li>
            </ul>
            
        </div>
    </div>
</template>

<script>
    import {mapGetters, mapActions} from 'vuex';

    export default {
        name: "ExampleComponent",
        data() {
            return {
                loading:false
            }
        },
        computed: {
            ...mapGetters(['getFeeds','getExperts','getPosts']),

        },
        methods: {
            ...mapActions(['fetchFeeds','fetchExperts','fetchPosts']),
        },
        mounted () {
            Promise.all([
                this.fetchFeeds,
                this.fetchExperts,
                this.fetchPosts])
                .then(values => {
                    this.loading = true;

                    console.log(values);
                })
                .catch(error => {
                    console.error(error)
                });

        }
    }
</script>

vuex.store - note I've combined all 3 into the one store. You could separate out, but then you would need to use name spacing

 const initialState = () => ({
        feeds: [],
        experts: [],
        posts: [],
    });

    const state = initialState();

    const getters = {
        hasFeeds (state) {
            return state.feeds.length === 0;
        },
        hasExperts (state) {
            return state.experts.length === 0;
        },
        hasPosts (state) {
            return state.posts.length === 0;
        },
        getFeeds (state) {
            return state.feeds;
        },
        getExperts (state) {
            return state.experts;
        },
        getPosts (state) {
            return state.posts;
        },
    };

    const actions = {
        fetchFeeds({ commit,getters,dispatch }, name) {
            return new Promise((resolve, reject) => {
                if (getters.hasFeeds()) {
                    resolve(getters.getFeeds())
                } else {
                    axios.get('api/get/feeds')
                        .then(response => {
                            commit('SET_NEWSFEED', response.data);
                            resolve(response.data)
                        })
                        .catch(error => {
                            reject(error)
                        })
                }
            });
        },
        fetchExperts({ commit,getters,dispatch }, name) {
            return new Promise((resolve, reject) => {
                if (getters.hasExperts()) {
                    resolve(getters.getExperts())
                } else {
                    axios.get('api/get/experts')
                        .then(response => {
                            commit('SET_EXPERTS', response.data);
                            resolve(response.data)
                        })
                        .catch(error => {
                            reject(error)
                        })
                }
            });
        },
        fetchPosts({ commit,getters,dispatch }, name) {
            return new Promise((resolve, reject) => {
                if (getters.hasPosts()) {
                    resolve(getters.getPosts())
                } else {
                    axios.get('api/get/posts')
                        .then(response => {
                            commit('SET_POSTS', response.data);
                            resolve(response.data)
                        })
                        .catch(error => {
                            reject(error)
                        })
                }
            });
        },
    };

    const mutations = {
        SET_NEWSFEED (state, data) {
            state.feeds.push(data);
        },
        SET_EXPERTS (state, data) {
            state.experts.push(data);
        },
        SET_POSTS (state, data) {
            state.posts.push(data);
        }
    };

    export default {
        state,
        getters,
        actions,
        mutations
    }


Activity icon

Replied to Inherit Trait In Blade View

@bvanhaastrecht I know for a fact that @inject works as we use a variety of custom blade services.

Example if you created a BladeServices class you could add Trait to the service or add methods to the service items

App\helpers\BladeServices.php


<?php

namespace App\Helpers;

use Illuminate\Support\Arr;


class BladeServices {

    /**
     * @param null $value
     * @return bool
     */
    public  function hasProductName($array)
    {
        return Arr::has($array, 'product.name');
    }

}


in your blade

@inject('service', 'App\helpers\BladeServices')
@extends('layout')
@section('content')

	@if($service->hasProductName(['product' => ['name' => 'Desk', 'price' => 100]]))
		<h1>Working!!!</h1>
	@endif
@endsection


Apr
16
3 months ago
Activity icon

Replied to How To Best Format Data For Use In JqTree

@vincej likewise been busy trying to write code ... the good news is ... I still suck at it ... lol ... on a serious note I just finished the painful process of researching nested sets, etc. and wrote Vue componenets for trees so let me know how I can help.

Activity icon

Replied to How To Best Format Data For Use In JqTree

@vincej the ugly, but simple approach is as follows. Note the roots need to null for parent and you will call the only root and it ill do the rest because we are loading all children of the model

In your model. Lets assume it is called Workspace

class Workspace extends Model
{



    /**
     * @var array
     */
    protected $with = [
        'children',
    ];


    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function children()
    {
       // assuming you have a parent_id setup in your model
        return $this->hasMany(Workspace::class, 'parent_id', 'id');
    }

}

Activity icon

Replied to How To Get The Index Value From Vi-for

@artizan if the data is a Laravel model then just return the id in your @click or if I read it right just return the category object as such

@click.prevent="editCategory(category)" 

component

        editCategory(category){
                // PS camelcase is best with JS i.e. categoryUpdate
                this.category_update = category; 
         },

if you want the id then just do the following:

@click.prevent="editCategory(category)" 

component

        editCategory({id}){
		// using lodash but you can use common JS filter, foreach, etc
                this.category_update = _.find(this.categories, (c) => c.id === id);
         },

Activity icon

Replied to VUEX State Variables Default

@apollobln sorry, yes, I inserted that because in my experience Vuex and components work best when reactivity of the component is coupled to the store through boolean methods. "Truthies" such as hydrated arrays and objects tend not to work as well. For example, return _.isEmpty(state.posts) works better than return state.posts. In this example, hasPosts() would be the former and getPosts() would be the latter.

It has been a steep learning curve for me as well, but as Im sure you already are experiencing, it is great once you get it right.

Example, of how I setup my stores

./store/store.js

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

import createLogger from 'vuex/dist/logger';
import modules from './modules/index';
const debug = process.env.NODE_ENV !== 'production';

export default new Vuex.Store({
    modules, // all your imported modules
    strict: debug,
    actions: {
        reset({commit}) {
            // resets state of all the modules
            Object.keys(modules).forEach(moduleName => {
                commit(`${moduleName}/RESET`);
            })
        }
    },
    plugins: debug ? [createLogger()] : [] // set logger only for development
})

./store/modules.index.js

NOTE: then I store all store files as module.store.js e.g. workspaces.store.js and as such all my modules are namespaces as such e.g. Workspace or products.store.js would be namespace Product

const requireModule = require.context('.', false,  /\.store\.js$/);
const modules = {};

requireModule.keys().forEach(filename => {
    // create the module name from fileName
    // remove the store.js extension and capitalize
    const moduleName = filename
        .replace(/(\.\/|\.store\.js)/g, '')
        .replace(/^\w/, c => c.toUpperCase());

    modules[moduleName] = requireModule(filename).default || requireModule(filename);
});

export default modules;

./store/modules/workspace.store.js


import { getSpaceOfModule,getAllSpaces,getSpacesOfName } from '../../api/apis/workspaces.api';

const initialState = () => ({
    workspaces: []
});

const state = initialState();

const getters = {
    getSpaces(state) {
        return state.workspaces;
    },
    hasSpaces(state) {
        return !_.isEmpty(state.workspaces);
    },
    getBySlug: state => slug => {
        return _.find(state.workspaces, ['slug', slug]);
    },
    getById: state => id => {
        return _.find(state.workspaces, ['id', id]);
    },
};

const actions = {
    reset({ commit }) {
        commit('RESET');
    },
    async fetchSpaces({ commit,getters,dispatch }, module) {
        try {
            const response = await getSpaceOfModule(module);
            dispatch('addSpace',{space:_.head(response.data)});
        } catch (error) {
            console.error('ERROR', error);
        }
    },
};


const mutations = {
    RESET(state) {
        const newState = initialState();
        Object.keys(newState).forEach(key => {
            state[key] = newState[key]
        });
    },
    INSERT_SPACE (state, space) {
        state.workspaces.push(space);
    },
};

export default {
    namespaced: true,
    state,
    getters,
    actions,
    mutations
}



in my vue component


       computed: {
            ...mapGetters('Workspace', ['getSpaces', 'hasSpaces']),

        },
        methods: {
		// references as this.fetchSpaces
            ...mapActions('Workspace', ['fetchSpaces']),

        },

Activity icon

Replied to How To Get Values From Db On Component Creation And Like Laravel's Old Method.

@theunforgiven it is fairly straigh forward. I dont know what v-toggle is I expect a toggle component, but using the renew button it would be something like this


<template>
<div>
    <ul class="flex flex-wrap">
        <tr v-for="(membership, index) in memberships" 
            :key="index">
            <td v-text="membership.name"></td>
            <td v-text="membership.number"></td>
            <td>{{ getHumanDate(membership.expiry) }}</td>
            <td>
                <toggle-button
                    v-model="wantsNotify"
                    :value="false"
                    :sync="true"
                    :labels="{checked: 'Yes', unchecked: 'No'}"
                />
                <input type="checkbox" v-model="wantsNotify">
            </td>
            <td>{{ '£' + parseFloat(membership.cost).toFixed(2) }}</td>
            <td v-if="membership.expiry ">
                <button @click="renew(membership)" 
                        class="btn btn-sm btn-outline-primary">
                    Renew
                </button>
            </td>
        </tr>
    </ul>

<!--        Example of member access when it returns-->
        <div>
            <p>Member of {{member.id}}</p>
            <p v-text="member.name"></p>
        </div>
</div>
</template>

<script>

    export default {
        name: "ExampleComponent",
        data() {
            return {
                member: {}
            }
        },
        methods: {
            renew({id}) {
                axios.get(`/member/` + id)
                    .then(response => {
                        // the response if member found on the backend
			this.member = response.data;
                        console.log(response.data);
                    })
                    .catch(error => {
                        console.log(error);
                    })
            },
        },
    }
</script>

Activity icon

Replied to [vuex] Module Namespace Not Found In MapActions()

@ahoi addProductToCart would be an action. I think you are attempting to call a getter versus action. If you want to load an action them it would be as follows. Note - I have not checked your Vuex code, but it sounds like have a reference error.

<template>
    <div class="flex flex-wrap">


    </div>
</template>

<script>
    import {mapGetters, mapActions} from 'vuex';

    export default {
        name: "ExampleComponent",
        data() {
            return {
                data: []
            }
        },
        computed: {
            ...mapGetters('cart',['getProducts','hasProducts','calclTotalPrice']),
            // Example: redundent, but to show you how you access the getter
            getAllProducts() {
                return this.getProducts;
            },
        },
        methods: {
            ...mapActions('cart',['addProduct','fetchProducts']),
            // Example of how to access namedspace actions
            addProductItem(item) {
                return this.addProduct(item);
            },
        },
    }
</script>

also you need to callout namespace as

export default {
   namespaced: true,
   state,
   getters,
   actions,
   mutations,
}


I think your Vuex is ok, but the basic template would be


const initialState = () => ({
    products: []
});

const state = initialState();

const getters = {
    getProducts (state) {
        return  state.products
    }
};


const actions = {
    addProduct({ commit,getters }, item) {

    },
};


const mutations = {
    INSERT_PRODUCT () {

    }
};

export default {
    namespaced: true,
    state,
    getters,
    actions,
    mutations
}

Activity icon

Replied to VUEX State Variables Default

@apollobln as I said you loading data in Vuex and expecting the component knows when the a day is there and will somehow sync. Vue does an excellent job when it is component and sometimes that will translate to Vuex but the truth is if you want to work then you need to build async i.e. promise based. SO if you request data in Vuex you will need to build a promise in the getters or promise back to the component. Example

Vuex fetchPosts example. We wrap the entire fetch in a promise which will return a promise to the component and you either return data or just act on the fulfilled promise, if that makes sense.

<script>
    getPosts ({commit,getters}, payload = '') {
        return new Promise((resolve, reject) => {
            if (getters.hasPosts) {
                // we return true and then will get them back in your component
                resolve(true)
            } else {

                axios.get(`${API}/posts/paginated?${payload}`, headers(getters))
                    .then(response => {
                        // remove your code for bervity sake
                        return resolve(true)
                    })
                    .catch(error => {
                        console.log(error);
                        reject(error)
                    })
            }
        });
</script>


component example


<template>
    <div class="flex flex-wrap">
<!--        if you want to use component reactivity-->
        <div v-if="hasPosts">
            <ArtikelCard class="cursor-pointer w-1/2"
                         v-for="(post, index) in getAllPosts"
                         :key="index"
                         :post="post"/>
        </div>
<!--        OR-->
<!--        if you want to use Vuex reactivity-->
        <div v-if="hasPosts">
            <ArtikelCard class="cursor-pointer w-1/2"
                         v-for="(post, index) in getPosts"
                         :key="index"
                         :post="post"/>
        </div>

    </div>
</template>

<script>
    import {mapGetters, mapActions} from 'vuex';

    export default {
        name: "ExampleComponent",
        data() {
            return {
                isLoading: false,
                data: []
            }
        },
        computed: {
            ...mapGetters(['getPosts', 'hasPosts']),
            getAllPosts() {
                // console.error("getActive", this.getActive);
                return this.data;
            },
        },
        methods: {
            ...mapActions(['getPosts'])
        },
        mounted() {
            this.getPosts
                .then(response => {
                    this.isLoading: false;
                    // AND/OR
                    this.data = response.data;
                    // OR
                    this.data = this.getPosts
                })
                .catch(error => {
                    console.log(error);
                    reject(error)
                })
        },
    }
</script>
Activity icon

Replied to VUEX State Variables Default

@apollobln sorry for the delay. I know these are frustrating as hell and the problem with webpack chunks is debugging is often difficult . I think the problem is simply an async issue. You are rendering before the data is set. There are workaround, but let start withs something simple as a timeout to see if that s the issue. Look at the code in the mounted section. Important that mounted is async or it will not work. We build a timer that will only set isLoading to true after 5 seconds.

Also, not that if you are going to use axios in Vuex and you are dependent on the data that you also need to follow the promise all the way through, but let's tart with timeout and I'll explain what I mean by axios in a followup post

<template>
    <div class="flex flex-wrap">
        <div v-if="isLoading">
            <ArtikelCard class="cursor-pointer w-1/2"
                         v-for="(post, index) in newsposts" :key="index"
                         :post="post"/>
        </div>

    </div>
</template>

<script>
    import ViewPort from "../config/services/ViewPort";

    export default {
        name: "ExampleComponent",
        data() {
            return {
                isLoading: false
            }
        },
        async mounted() {
            function timeOut() {
                return new Promise(function (resolve, reject) {
                    window.setTimeout(function () {
                        resolve('done!');
                    }, 5000);
                });
            }
            this.isLoading = false;
            const result = await timeOut();
            this.isLoading = true;
        }
    }
</script>


Apr
13
3 months ago
Activity icon

Replied to Create A File On Local Storage

@illmatic I believe you are attepting to create an image file from a base64 string. If so take a look at http://image.intervention, specifically http://image.intervention.io/api/make

        //IMAGE INTERVENTION TO BASE64
        $data = (string) Image::make('public/bar.png')->encode('data-url');
        

        //IMAGE INTERVENTION FROM BASE 64 TO SAVE AS PNG OR JPEG
        $img = Image::make($base64String)->save('public/bar.png');

        // WITHOUT IMAGE INTERVENTION
        $image = base64_decode($base64String);
        $image_name= 'file_name.png';
        $path = public_path() . "/images/" . $image_name;
        file_put_contents($path, $image);


Activity icon

Replied to Best Way To Deal With One Time Notifications?

You welcome sir. Hope it helps. That said there might be folks with better approaches.

Activity icon

Replied to Stop Adding Poor Quality Laravel Addons

@martinbean it is less a product issue than more of an author ego comment. Sanctum is new so to be fair it needs some runway. Whereas Socialite is social auth, doesn't get simpler and more specific than that ... setup the redirect, open a JS window, make a request which then provides a redirect to social provider and you have auth ... in theory. Unless you you have certain session or cors configurations or you using JWT or Sanctum, in which case OAuth1 issues or attempt to decorate to fix the issues. Again all ok as products have issues, but when people post the issues don't just close out without any feedback only to see people asking the same questions 4 years later with still no change to documentation or product. The onuses is on the Laravel community to let one another know this is not a solid product nor does it have the support. It happens anyway as people keep asking me if I found a solution to the problem I posted in 2015 and go read the problems on this forum alone?

Activity icon

Replied to Stop Adding Poor Quality Laravel Addons

@siangboon agree with your assessment.

Activity icon

Replied to VUEX State Variables Default

@apollobln

The problem with JS is that is not async unless you code it that way i.e. you could load a module without the data being there and if the condition fails without a promise then you will get the null or undefined issue

Im using mapActions and mapGetters, but you can use $store. First look for posts then use async and await. You could use classic Promise as well

    import {mapActions, mapGetters} from "vuex";
    export default {
        name: "Posts",
        data() {
            return {
                isLoading: false
            }
        },
        computed: {
            ...mapGetters('Posts', ['getPosts']),
        },
        methods: {
            ...mapActions('Posts', ['fetchPosts']),

        },
        async mounted() {
	    // I'm using mounted but you could have an async method
            if (this.getPosts.length === 0) {
                this.isLoading = true;
                await this.fetchPosts();
                this.isLoading = false;
            }
        },

then you would have something like this for posts. Ive not tested it

    const initialState = () => ({
        posts: []
    });

    const state = initialState();

    const getters = {
        getPosts(state) {
            return state.posts;
        },
        hasPosts(state) {
            return !_.isEmpty(state.posts);
        },
    };

    const actions = {
        async fetchPosts({ commit,getters,dispatch }) {
            try {
                const {data}  = await axios.get('/api/psots');
                commit('SET_POSTS',data);
            } catch (error) {
                console.error('ERROR', error);
            }
        },
    };


    const mutations = {

        SET_POSTS (state, data) {
            state.posts = data;
        },
    };

    export default {
        // namespaced: true, /// remove if no namespacing 
        state,
        getters,
        actions,
        mutations
    }
``
Activity icon

Replied to Vue Computed Properties Reactivity

@apollobln

Without seeing the complete code a couple of points:

  1. v-if removes the code form the DOM v-show that hides visibility. In some cases the DOM will render and once rendered you will either need to render() again. So explore v-if vs v-show. Especially with a sub component such as . You might find v-show fixes that for you. Yes you also might need add some CSS to ode the element with v-show like translate or width/height
  2. not good practice to use collections for boolean. Works in most cases, but I've run into Vuex problems Computed properties work best with booleans, subtle I know. So I would god with something like a getter
  3. you can use a watch or observer, but I find when I use a watch Ive screwed up something in the code and now forcing it
  4. again without seeing the code always best to use promise for getting posts, which will help reactivity. I love new JS ``await``` and nowadays most of my code is wrapped in promises as VueX, VueRouters etc play havoc on reactivity.

    hasPosts(state) {
        return !_.isEmpty(state.structure); // lodash but use can length for common JS
    },
Activity icon

Replied to Best Way To Deal With One Time Notifications?

@chrisgrim not at all. Local storage will always be much faster than server requests and 20 local storage requests is better than 20 server requests. That said, 20 server requests is really not an issue. The best way to think about it is that if you are planning to run some sort of analytics or provide some sort of dashboard / meaningful statistics then store it in a DB, if the data is important then store it in DB, if customer experience then DB, because users had being asked the same 20 questions if they have already completed it, but if it is settings that could range from 1 to 20 events then I see not reason not store in storage, but again I wouldn't be concerned about traffic with that many server requests.

That said you could use mutators and accessors to do the work for setting and getting the array, but then you would need to create CRUD functionality for the array.

Lets say you had 1 - x events fields in an array you could store it in a single field in a table

Example array :

        $events = [
           false, // you would need to know that position 0 is x field / column 
           true,  // and position 1 is y field / column
           //  ... n amount of fields
        ];

So if you had 20 events, each user would have an events column with 20 array values store in the table column Then in your model you would retrieve and set the array with something like this


    /**
     * @return array
     */
    public function getEventsAttribute()
    {
        return explode(",", $this->events);
    }

    /**
     * @param array $field
     */
    public function setEventsAttribute(array $field)
    {
        $this->events = implode(",", $field);
    }


    /**
     * @param $idx
     * @return |null
     */
    public function getEvent($idx)
    {
        return count($this->events) >= $idx
            ? $this->events[$idx]
            : null;
    }


if you storing something more than boolean you could use an Enum package to standardize values


<?php

namespace Enums;

use MabeEnum\Enum;

class EventsEnum extends Enum
{
    const EVENT_TYPE_1              = 0;
    const EVENT_TYPE_2              = 1;
    const EVENT_TYPE_3              = 2;
    
}


then you would retrieve the value


    public function getEventValue($int)
    {
        EventsEnum::getConstant($int);
    }


Activity icon

Replied to Issues With Partial JS Files

Could be a number of problems. Here is an approach that might help. Dont know if JQuery ajax returns a promise or just data. Im assuming promise in which case this will work.

<script>

//admin.js
export default class Admin {
    storeEdit(event) {
        event.preventDefault();
        var url = $(event.target).attr('data-id');
        console.log(url);
        $.ajax({
            type: 'GET',
            url: url,
            dataType: 'json',
            success: function success(result) {
                return result;
            }
        });
    }
}
</script>

// main.js
<script>
    import Admin from '../Admin'
    
    const admin = new Admin();

    $('.storeEdit').on('click', function (event) {
        admin.storeEdit(event)
            .then (result => {
                $("input[name='name']").attr('value', result.name);
                $("input[name='id']").attr('value', result.id);
                $("input[name='internal_number']").attr('value', result.internal_number);
                $("input[name='external_number']").attr('value', result.external_number);
                $("input[name='address']").attr('value', result.address);
                $('#editStore').modal('show');
            })
    });
</script>

Activity icon

Replied to Help Me To Make Online Notepad Using Javascript.

@johnpatel look at any of the WYSIWYG editors e.g. CKEditor, Quill, TinyMce

Activity icon

Replied to Best Way To Deal With One Time Notifications?

@chrisgrim look at JSCookie ... takes two seconds to setup and implement.

Activity icon

Replied to Pass From Parent To Child To Custom Component

@rhys two approaches

OPTION 1



// PARENT
<template>
    <div class="relative w-full mt-6">
        <child v-model="form.name"></child>
    </div>
</template>
<script>
    import Child from "../../app/Child";

    export default {
        name: "Parent",
        components: {
            Child
        },

        data() {
            return {
                form:{
                    name: ""
                }
            }
        },
    };
</script>


<template>
    <div>
        <input
            id="name"
            type="text"
            v-model="name"
            autocomplete="on"
            placeholder="Name"
            class="form--input light"/>
    </div>
</template>

<script>
    export default {
        name: "Child",
        props: ['value'],
        computed: {
            name: {
                get() {
                    return this.value;
                },
                set(value) {
                    this.$emit("input", value);
                }
            }
        }
    };
</script>


OPTION 2

// PARENT
<template>
    <div class="relative w-full mt-6">
        <child v-bind.sync="form.name"></child>
    </div>
</template>
<script>
    import Child from "../../app/Child";

    export default {
        name: "Parent",
        components: {
            Child
        },
        watch: {
            'form.name'(val) {
                // once clicked on the child component you will see value change in parent
                console.log('------- form name ', val);
            },
        },
        data() {
            return {
                form:{
                    name: ""
                }
            }
        },
    };
</script>



<template>
    <div>
        <button @click="changeValue('someValue')"></button>
    </div>
</template>

<script>
    export default {
        name: "Child",
        props: ['value'],
        methods: {
            changeValue(val) {
                this.$emit('update:value', val)
            },
        }
    };
</script>