hakhsin

hakhsin

Member Since 5 Months Ago

Experience Points
25,090
Total
Experience

4,910 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
212
Lessons
Completed
Best Reply Awards
2
Best Reply
Awards
  • start-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-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-token Created with Sketch.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer-token Created with Sketch.

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • lara-evanghelist 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 6
25,090 XP
Dec
12
4 days ago
Activity icon

Awarded Best Reply on The Path Of Subdomains Don't Work

Hi @sinnbeck, I found out this:

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    RewriteEngine On

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)/$ / [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
</IfModule>

It is good in your mind? Do you have a recommendation for it?

Dec
05
1 week ago
Activity icon

Replied to Why This Code On Shared Host Doesn't Work?

Hi @sinnbeck, it returns null with 200 status code. No, I don't get any error in storage/logs/laravel.log.

Activity icon

Started a new Conversation Why This Code On Shared Host Doesn't Work?

Hi, here is my login function:

/**
     * Handle a login request to the application.
     *
     * @param \Illuminate\Http\Request $request
     * @return \Illuminate\Http\Response|\Illuminate\Contracts\Routing\ResponseFactory
     *
     * @throws \App\Exceptions\BadRequestException
     */
    public function login(Request $request)
    {
        $validateDate = $this->validateLogin($request);

        try {
            $response = (new Client())->post(route('passport.token'), [
                'form_params' => [
                    'grant_type' => 'password',
                    'client_id' => $this->getClientId(),
                    'client_secret' => $this->getClientSecret(),
                    'username' => $validateDate['username'],
                    'password' => $validateDate['password'],
                    'scope' => $this->getScope($validateDate),
                ]
            ]);

            User::emptyOtp($validateDate['username']);

            return $response;
        } catch (GuzzleHttpBadResponseException $e) {
            throw new BadRequestException(__('auth.failed'));
        }
    }
        

This code in localhost works but on shared host doesn't work. But if I write return response($response->getBody()); instead of return $response; it works! Why do it happened?

Activity icon

Replied to The Path Of Subdomains Don't Work

Hi @sinnbeck, I found out this:

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    RewriteEngine On

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)/$ / [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
</IfModule>

It is good in your mind? Do you have a recommendation for it?

Dec
04
1 week ago
Activity icon

Replied to The Path Of Subdomains Don't Work

@sinnbeck when I open example.com, I get 404. I meant www.example.com and example.com are different for my app.

Activity icon

Replied to The Path Of Subdomains Don't Work

@sinnbeck no, I see error 404.

Activity icon

Replied to The Path Of Subdomains Don't Work

This is my subdomain config on cpanel subdomain.

Activity icon

Replied to The Path Of Subdomains Don't Work

Hi @sinnbeck, I don't know what is frontpage. I google it but google give me Microsoft Front Page. Can you describe it for me, please?

Here is my RouteServiceProvider:

  /**
     * Define the "web" routes for the application.
     *
     * These routes all receive session state, CSRF protection, etc.
     *
     * @return void
     */
    protected function mapWebRoutes()
    {
        Route::name('web.')
            ->middleware(['web'])
            ->domain(subdomain(env('WEB_SUBDOMAIN')))
            ->namespace($this->namespace . '\Web')
            ->group(base_path('routes/web.php'));
    }

    /**
     * Define the "api" routes for the application.
     *
     * These routes are typically stateless.
     *
     * @return void
     */
    protected function mapApiRoutes()
    {
        Route::middleware(['api'])
            ->domain(subdomain(env('API_SUBDOMAIN', 'api')))
            ->namespace($this->namespace . '\Api')
            ->group(base_path('routes/api.php'));
    }
Activity icon

Started a new Conversation The Path Of Subdomains Don't Work

Hi, I have a shared host. In local host everything work good but when I upload my project on my host the path of subdomain doesn't work. I mean when I open www.example.com or api.example.com they work but if I want to open api.example.com/login or any other paths I get 404 error. Why do happen those? What do I do?

Activity icon

Replied to Get CSRF Token Mismatch When Trying Destroy A Token

@nakov I thought this approach was better because there is revoked column. Not are there? If your approach is better I will delete it.

Activity icon

Replied to Get CSRF Token Mismatch When Trying Destroy A Token

Thanks @nakov. So I understood for both usage, Android and Vue the best way is implement my functionality. Is this true? If yes, is this function good? I means, doesn't need it to revoke refresh token?

/**
     * Remove the specified token from user's tokens.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        $result = auth()->user()->tokens()->where('id', $id)->update(['revoked' => true]);
        return response('', $result ? Response::HTTP_NO_CONTENT : Response::HTTP_NOT_FOUND);
    }
Activity icon

Replied to Get CSRF Token Mismatch When Trying Destroy A Token

@nakov I am using Vue, and Android App.

Activity icon

Replied to Get CSRF Token Mismatch When Trying Destroy A Token

@nakov this is my case:

If you are hitting the route from your app then just put the CSRF token in the header.

How can I set CSRF token in the header?

Activity icon

Awarded Best Reply on Get All User's Tokens With Laravel Passport

We have to set default user guard to 'api'.

Activity icon

Replied to Get All User's Tokens With Laravel Passport

We have to set default user guard to 'api'.

Activity icon

Replied to Get CSRF Token Mismatch When Trying Destroy A Token

@nakov I changed default api url with this code:

    /**
     * Define the "web" routes for the application.
     *
     * These routes all receive session state, CSRF protection, etc.
     *
     * @return void
     */
    protected function mapWebRoutes()
    {
        Route::name('web.')
            ->middleware(['web'])
            ->domain(subdomain(env('WEB_SUBDOMAIN')))
            ->namespace($this->namespace . '\Web')
            ->group(base_path('routes/web.php'));
    }

    /**
     * Define the "api" routes for the application.
     *
     * These routes are typically stateless.
     *
     * @return void
     */
    protected function mapApiRoutes()
    {
        Route::middleware(['api'])
            ->domain(subdomain(env('API_SUBDOMAIN', 'api')))
            ->namespace($this->namespace . '\Api')
            ->group(base_path('routes/api.php'));
    }

Actually I have 3 subdomains: web, api and oauth. oauth subdomain is for laravel passport routes. That web middleware by default sets for it. Are there any why that I can force laravel to used api middleware for that?

Activity icon

Replied to Get CSRF Token Mismatch When Trying Destroy A Token

@nakov yes, it is default passport route that I changed its url (subdomain) with this:

Passport::routes(function ($router) {
            $router->forAccessTokens();
        }, [
            'domain' => subdomain(env('OAUTH_SUBDOMAIN', 'oauth')),
            'prefix' => ''
        ]);

How can I force laravel to use api middleware for that? And here is a image when I hit that route directly: result

Activity icon

Replied to Get CSRF Token Mismatch When Trying Destroy A Token

Hi @nakov, here is my route in api.php:

...
Route::delete('tokens/{id}', 'Auth\[email protected]')->name('tokens.destroy');
...

But I try use own passport route. I mean when a users request I wrap it to passport route by GuzzleHttp. I saw this approach in youtube, is this good? here is my route list:

+--------------------+----------+-------------------+-------------------------+---------------------------------------------------------------------------+------------------------+
| Domain             | Method   | URI               | Name                    | Action                                                                    | Middleware             |
+--------------------+----------+-------------------+-------------------------+---------------------------------------------------------------------------+------------------------+
| www.shahsin.test   | GET|HEAD | /                 | web.                    | Closure                                                                   | web                    |
| api.shahsin.test   | POST     | login             |                         | App\Http\Controllers\Api\Auth\[email protected]                       | api,guest,throttle:6,1 |
| api.shahsin.test   | POST     | logout            | logout                  | App\Http\Controllers\Api\Auth\[email protected]                      | api,auth:api           |
| api.shahsin.test   | POST     | send-otp          |                         | App\Http\Controllers\Api\Auth\[email protected]                       | api,guest,throttle:2,1 |
| oauth.shahsin.test | POST     | token             | passport.token          | Laravel\Passport\Http\Controllers\[email protected]        | throttle               |
| oauth.shahsin.test | GET|HEAD | tokens            | passport.tokens.index   | Laravel\Passport\Http\Controllers\[email protected] | web,auth               |
| api.shahsin.test   | GET|HEAD | tokens            | tokens.index            | App\Http\Controllers\Api\Auth\Token[email protected]                       | api,auth:api           |
| api.shahsin.test   | DELETE   | tokens/{id}       | tokens.destroy          | App\Http\Controllers\Api\Auth\[email protected]                     | api,auth:api           |
| oauth.shahsin.test | DELETE   | tokens/{token_id} | passport.tokens.destroy | Laravel\Passport\Http\Controllers\[email protected] | web,auth               |
| api.shahsin.test   | GET|HEAD | user              | user                    | Closure                                                                   | api,auth:api           |
+--------------------+----------+-------------------+-------------------------+---------------------------------------------------------------------------+------------------------+

and my default user guard is 'api'.

Activity icon

Started a new Conversation Get CSRF Token Mismatch When Trying Destroy A Token

Hi, When I try to destroy a token I get "Get CSRF token mismatch" error. How should I solve it? I know the reason is CSRF token. My app is restFul api.

Activity icon

Awarded Best Reply on Apache2 Ubuntu Default Page Shows If I Don't Set Valent Port

I had to change apache2 port. That's it.

Dec
03
1 week ago
Activity icon

Replied to Apache2 Ubuntu Default Page Shows If I Don't Set Valent Port

I had to change apache2 port. That's it.

Activity icon

Started a new Conversation Apache2 Ubuntu Default Page Shows If I Don't Set Valent Port

Hi, I am new in valent. When I open my site like this www.shahsin.test I get Apache2 Ubuntu Default Page, but if opens it like this www.shahsin.test:8080 I see my site. How can I fix it?

Nov
28
2 weeks ago
Activity icon

Started a new Conversation Get All User's Tokens With Laravel Passport

Hi, how can I get all user's tokens in laravel passport? I did this: After I get a token I set it to authorization in posman and I try to get all user tokens by request to oauth.shahsin.test/tokens but I got this error: "message": "Unauthenticated.". What do I do for get all tokens? I am using Password Grant Tokens.

Nov
11
1 month ago
Activity icon

Started a new Conversation How To Debuge Php Packages

Hi, I am trying to add a feature for Laravel Passport. My problem are I can't see the value of variables. How can I find out what key-value exists in the variables?

Activity icon

Started a new Conversation How To Determine Current User Provider

Hi, how can I determine current User Provider?

See here!

Auth::shouldUse($guard);

Now, I want to know what is the guard or its provider.

Nov
09
1 month ago
Activity icon

Started a new Conversation Are A Morphs Columns Indexed?

Hi, when do I define a morphs columns in migration by default its columns are indexed?

Activity icon

Started a new Conversation What Do I Response After User Registered With API?

Hi, Which one of below response is the best practice after user registered?

a- Return user's information, like username, email, and etc.

b- Return Access Token.

Are there any convention for this case?

Nov
07
1 month ago
Activity icon

Awarded Best Reply on Authenticate Multi Type Of Users With Password Grant

Hi everyone, I solved it in multi step:

1- I create a fork of laravel/passport;

2- I maintain my fork and commit it in a new branch; larasin-passport

3- I depended my fork on composer.js. Guide

Activity icon

Replied to Authenticate Multi Type Of Users With Password Grant

Hi everyone, I solved it in multi step:

1- I create a fork of laravel/passport;

2- I maintain my fork and commit it in a new branch; larasin-passport

3- I depended my fork on composer.js. Guide

Nov
05
1 month ago
Activity icon

Replied to Authenticate Multi Type Of Users With Password Grant

Hi @jlrdw, I try to implement this feature for laravel passport. I don't know it's true. I pulled this commit : Passport Multi Auth. I wanted when the user publish config file php artisan vendor:publish --tag=passport-config he can defines his provider-selector. Can you check it for correction my possible wrongs?

Nov
04
1 month ago
Activity icon

Replied to Authenticate Multi Type Of Users With Password Grant

Hi @jlrdw, I am talking about laravel passport, Password Grant Client.

Activity icon

Replied to Vue Not Recognizing Divs On Other Pages In Laravel

سلام شهاب! خخخ. یکم مرتبتر مینویسی؟ من متوجه نشدم! چون علايم نگارشی استفاده نکردی.

Activity icon

Replied to Pass Data From Blade To Vue Component

Hi @cyprous, Try this:

<my-list :list="{{ json_encode($list) }}"> </my-list>
Activity icon

Started a new Conversation Authenticate Multi Type Of Users With Password Grant

Hi, I have 2 type users in my app, Admin and User. How can I using Password Grand Client for authentication for both Admins and Users? In default it only work for User authentication. I mean when I request to www.example.test/oauth/token this data:

'grant_type' => 'password',
'client_id' => '3',
'client_secret' => '1bPt013QnWCWERwfthZ1tVEVG02RouFwD6JpEnL4',
'username' => '[email protected]',
'password' => 'password',
'scope' => '',

I got this response:

{
    "token_type": "Bearer",
    "expires_in": 1296000,
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjYxNjcxN2E4OTI0ZTIzMGMzZjE5YTkwNTcwZTlmODdhYjE2NjVhZGQxZmY2MzRkMjk5NmM5MGM1Yzk1NjU5OWJjZDQ0NzEyOTgxOTY4M2Y5In0.eyJhdWQiOiIzIiwianRpIjoiNjE2NzE3YTg5MjRlMjMwYzNmMTlhOTA1NzBlOWY4N2FiMTY2NWFkZDFmZjYzNGQyOTk2YzkwYzVjOTU2NTk5YmNkNDQ3MTI5ODE5NjgzZjkiLCJpYXQiOjE1NzI4NzczMDMsIm5iZiI6MTU3Mjg3NzMwMywiZXhwIjoxNTc0MTczMzAzLCJzdWIiOiIyIiwic2NvcGVzIjpbXX0.DZtVXO4-pluinw3gLQ87bLuq-j8ILWF47EpAXO69Jf0jDF5cQjqh-o6IjUnXuRUGxjrie8UYq_m1CuxlRdPuJzuTD46w6fZKzFgHR2qoZAP5k5yaPm1yNqHO3MTvthXchzfNrCpu5qhNS2z2bxFp9BptX_w9vPaz_BaPojAii84l_qLfrk8nvqT1jWiEOBGCBzZwd6btjcQq79pOxNFUmChWGuBDQcH9k3kyirEt01PkIGAj89_b2F3Cc6xw29z-6vdTg8J_44KCJpEjNImcW61ze1x_EZqYSw0Y-KstdTdPKsY_crNmPp1w0ONrheVBb1eo4TjReutJ-Fc0-ddIaPdoKvoXUHN8wkcB5BtNrInAbGUUnBetm0SVJ3XWvJumjV3urJ209u_jVwyIF7ICVBheB4TaMLeB_NfrL593jWuggqSPHnCS-Inytb2i8zsaKXWdJ_u4xKO_1f-JXxvkhJelkldd9dcAGbALKCxN8CrCA8OAlAzRn2p5dBYf2tuaZIA1AxpTQuuybSx0C3MoJOh-VX1nQc5WWKB3fYmaOOPJi2KxiMLjOvap8GJZPbbLYOieVdfuhbqCEA1olT0wLjiDsl7RfJ5EOonhxTPAzGwIgIoyfAmUl849CKTQER5ORZzmbOxZSPKT51jxTKF_N1NYdCVgaeFaA5HghtBeJpA",
    "refresh_token": "def502006f4426c9e28cee17ed5934f00ee7ce778c51d1587efe968e72b8390124599d6b063dd57584aef2a3ce8704779e27b0b7daf1fd11f3666000deabb5746fcd51bd0ff45edc4a7c1287d00fb738a22644ff66200e112cc7f89445ec24010d6cff1cc0f7089ecacc832dc7841936f6808f051b3beafe4f19935b469f981461ed548c14bbd395afd0a16587f08fb831bc4d50fdd16c5497d8a04a5355137e15ce2df44b0682a4270ad190179fe13184c9830cb0146174efc15ebae4ad1fc206c6a145b01f3a2bd3fd27d081204f90d9a0d2e8012453d059a7dbea4a13e87f70e57808b2684f65d4a32f5580a0c0e7e67e48dac16b5ec9ddae08ec2791808c1725aa0e20332bae2d9df18911ca6490a936398fa897b0d68e549e26421f83c8c7314e45f0bc92120c4b22db11206b5f9f2a1361397d0e39636f115a6fe2eab771a48d05ea9cea79cee77b0382b536389e6269a78f4746213d3d8b8d277cfb25a8"
}

Now, what do I do for authenticate a Admin?

Activity icon

Awarded Best Reply on Vue: Sync Data With Property In A Child Component

Hi @ideasfera, you can use v-model for custom component. article

Oct
24
1 month ago
Activity icon

Replied to Add Class To V-node

Hi @ahmeddabak, I write a code like this. But the problem is when I change the class in v-node. In this situation all classes that I had bonded in html element will disappear. Here is my code:

this.$el.classList.add(newClass);
Activity icon

Started a new Conversation Add Class To V-node

Hi, I have a mixin named vuesin. In this mixin I want to add a class name to all vue instance. How can I do it? Is there any way to manipulate v-node?

Activity icon

Started a new Conversation Best Practice For Implement Two Direction Components

Hi, what is the best practice for implement a vue component library with two direction? Is the best way to create two css style?

Oct
23
1 month ago
Activity icon

Started a new Conversation Access To Classes That They Bind To The Element

Hi, how can I access to class property in a vue instance? I mean in bellow example I want to access to class prop in ps-pimosin element.

<ps-pimosin id="pimosin" :class="['theme-light', direction]" :value="value">
    <router-view />
</ps-pimosin>

In pimosin.vue:

methods:{
    example(){
        console.log(this.$props.class);
    }
}
Oct
17
1 month ago
Activity icon

Replied to Vue: Sync Data With Property In A Child Component

Hi @ideasfera, you can use v-model for custom component. article

Activity icon

Replied to Disable Unused Variable Error

@bobbybouwmann, cant It related to using local dependence? Here is my package.json:

{
  "name": "pimosin",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "core-js": "^2.6.5",
    "vue": "^2.6.10",
    "vue-router": "^3.0.3",
    // Here is my local dependency!
    "vuesin": "D:\Projects\Hakhsin\vuesin",
    "vuex": "^3.0.1"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^3.12.0",
    "@vue/cli-plugin-eslint": "^3.12.0",
    "@vue/cli-service": "^3.12.0",
    "babel-eslint": "^10.0.1",
    "eslint": "^5.16.0",
    "eslint-plugin-vue": "^5.0.0",
    "sass": "^1.19.0",
    "sass-loader": "^8.0.0",
    "tailwindcss": "^1.1.2",
    "vue-template-compiler": "^2.6.10"
  }
}

Because when I update vuesin package I get those errors.

Activity icon

Replied to Disable Unused Variable Error

Hi @bobbybouwmann, I changed it but it dosen't work. result. (I restarted local server.)

Activity icon

Started a new Conversation Disable Unused Variable Error

Hi, how can I disable unused variable error? I know I have to add this 'vue/no-unused-vars': 'off' to .eslintrc.js but it doesn't work for me. Now, what do I do? Here is my .eslintrc.js file content:

module.exports = {
  root: true,
  env: {
    node: true
  },
  'extends': [
    'plugin:vue/strongly-recommended',
    'eslint:recommended'
  ],
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'vue/no-unused-vars': 'off'
  },
  parserOptions: {
    parser: 'babel-eslint'
  }
};
Oct
12
2 months ago
Activity icon

Replied to Multiple User Authentication System

Hi @harshamv. Yes, it's my repo. Yes, ask me here.

Activity icon

Replied to Multiple User Authentication System

Hi @harshamv, in this repo I do it and commit it. larasin. See this commit: Manage Multiple Authentication.

Oct
09
2 months ago
Activity icon

Replied to Why My Drop-down Menu In Chrome Doesn't Work?

That's true but why when I create my component with pure html-css, I don't need to set it? Please see here.

Activity icon

Replied to Why My Drop-down Menu In Chrome Doesn't Work?

Thank you @sinnbeck. It works. Why I have to set top 100%?

Activity icon

Replied to Why My Drop-down Menu In Chrome Doesn't Work?

Hi @sinnbeck, I try it but my problem doesn't solve.

Activity icon

Replied to Why My Drop-down Menu In Chrome Doesn't Work?

Hi @munazzil, I try your solution but my problem doesn't solve.

Activity icon

Started a new Conversation Why My Drop-down Menu In Chrome Doesn't Work?

Hi, i create a navigation component that insert all my drop-down menu with a json. Here is my component:

My navigation component:

<script >
import "./index.scss";
import Recursive from "./recursive";
const MENU_PREFIX = "vs-menu-";

export default {
  name: "Navigation",
  inheritAttrs: false,
  status: "prototype",
  release: "1.0.0",
  render(h) {
    return h(
      this.type,
      {
        class: ["vs-navigation", this.variation]
      },
      [
        this.value.map(menu => {
          let button = this.$scopedSlots.button
            ? h(
                "div",
                {
                  on: {
                    click: e => this.clickHandler(menu, e)
                  },
                  class: "vs-nav-button"
                },
                [
                  this.$scopedSlots.button({
                    node: menu
                  })
                ]
              )
            : h(
                "vs-button",
                {
                  on: {
                    click: e => this.clickHandler(menu, e)
                  },
                  class: "primary md min-w"
                },
                [menu.label]
              );

          let subMenu = menu.nodes
            ? h("vs-recursive", {
                props: {
                  type: "ul",
                  value: menu.nodes
                },
                scopedSlots: {
                  default: this.$scopedSlots.default
                },
                ref: MENU_PREFIX + menu.id,
                class: ["vs-menu", "vs-hidden"]
              })
            : null;

          return h(
            "div",
            {
              directives: subMenu
                ? [
                    {
                      name: "click-outside",
                      expression: "clickOutside",
                      arg: menu.id
                    }
                  ]
                : null,
              class: "vs-nav-menu"
            },
            [button, subMenu]
          );
        })
      ]
    );
  },
  components: {
    "vs-recursive": Recursive
  },
  props: {
    type: {
      type: String,
      default: "nav"
    },
    variation: {
      type: String,
      default: "default",
      validator: value => {
        return value.match(/^(default|custom)$/);
      }
    },
    value: {
      type: Array,
      default: () => {
        return [];
      }
    }
  },
  methods: {
    clickHandler(node, e) {
      node.nodes ? this.toggle(node.id) : this.$emit("click", node, e);
    },
    close(ref) {
      if (!this.$refs[MENU_PREFIX + ref]) return;
      this.$refs[MENU_PREFIX + ref].$el.classList.add("vs-hidden");
    },
    toggle(ref) {
      this.$refs[MENU_PREFIX + ref].$el.classList.toggle("vs-hidden");
    },
    clickOutside(e, binding) {
      this.close(binding.arg);
    }
  }
};
</script>

My recursive component:

<script >
import { isArray } from "util";
const SUB_MENU_PREFIX = "vs-sub-menu-";
export default {
  name: "recursive",
  inheritAttrs: false,
  /**
   * Components in the system are labelled with status labels that reflect their
   * state of completion. See example below. All available statuses are:
   *
   * STATUS:        COLOR:     DESCRIPTION:
   *
   * deprecated     Red        Component is deprecated
   * prototype      Blue       Prototype, do not implement!
   * under-review   Yellow     Component is currently being reviewed
   * ready          Green      Ready to be used
   */
  status: "prototype",
  release: "1.0.0",
  render(h) {
    let items = this.value.map(node => {
      let item = h(
        "li",
        {
          on: {
            click: e => this.clickHandler(node, e)
          },
          directives: this.isSubMenu(node)
            ? [
                {
                  name: "click-outside",
                  expression: "clickOutside",
                  arg: node.id
                }
              ]
            : null,
          class: [{ "vs-item": this.isItem(node), "vs-label": this.isSubMenu(node) }]
        },
        [
          this.$scopedSlots.default
            ? this.$scopedSlots.default({
                node: node,
                state: {
                  isItem: this.isItem(node),
                  isSubMenu: this.isSubMenu(node)
                }
              })
            : node.label
        ]
      );

      let subMenu = node.nodes
        ? h("recursive", {
            ref: SUB_MENU_PREFIX + node.id,
            props: {
              value: node.nodes
            },
            scopedSlots: this.$scopedSlots,
            class: "vs-items vs-hidden"
          })
        : null;

      return subMenu
        ? h("ul", { class: "vs-sub-menu" }, [item, subMenu])
        : item;
    });

    return h(this.type, [items]);
  },
  props: {
    type: {
      type: String,
      default: "ul"
    },
    value: {
      type: Array,
      required: true
    }
  },
  methods: {
    isItem(node) {
      return !isArray(node.nodes);
    },
    isSubMenu(node) {
      return !this.isItem(node);
    },
    close(ref) {
      if (!this.$refs[SUB_MENU_PREFIX + ref]) return;
      this.$refs[SUB_MENU_PREFIX + ref].$el.classList.add("vs-hidden");
    },
    toggle(node) {
      this.$refs[SUB_MENU_PREFIX + node.id].$el.classList.toggle("vs-hidden");
    },
    clickHandler(node, e) {
      if (this.isSubMenu(node)) {
        this.toggle(node);
      }

      this.$emit("click", node, e);
    },
    clickOutside(e, binding) {
      this.close(binding.arg);
    }
  }
};
</script>

If I set this json:

{
        id: 'user_profile',
        label: 'User Profile',
        icon: 'user',
        view: 'user-profile.index',
        nodes :[
            {
                id: 'user_profile_sub_item_2',
                label: 'User Profile Sub Item',
                icon: 'user',
                view: 'user-profile.index',
            },
            {
                id: 'user_profile_sub_menu',
                label: 'User Profile Sub Menu',
                icon: 'user',
                view: 'user-profile.index',
                nodes:[
                    {
                        id: 'user_profile_sub_item_0',
                        label: 'User Profile Sub Item 0',
                        icon: 'user',
                        view: 'user-profile.index',
                        nodes:[
                            {
                                id: 'user_profile_sub_item_0_0',
                                label: 'User Profile Sub Item 0-1',
                                icon: 'user',
                                view: 'user-profile.index',
                            },
                            {
                                id: 'user_profile_sub_item_0_1',
                                label: 'User Profile Sub Item 0-2',
                                icon: 'user',
                                view: 'user-profile.index',
                            }
                        ]
                    },
                    {
                        id: 'user_profile_sub_item_1',
                        label: 'User Profile Sub Item',
                        icon: 'user',
                        view: 'user-profile.index',
                    }
                ]
            }
        ]
    },

    // Articles
    {
        id: 'posts',
        label: 'Posts',
        icon: 'blog',
        view: 'article.index'
    },

The output will be this:

<nav class="vs-navigation default">
    <div class="vs-nav-menu"><button type="button" class="vs-button default primary md min-w">User Profile</button>
        <ul class="vs-menu">
            <li class="vs-item">User Profile Sub Item</li>
            <ul class="vs-sub-menu">
                <li class="vs-label">User Profile Sub Menu</li>
                <ul class="vs-items vs-hidden">
                    <ul class="vs-sub-menu">
                        <li class="vs-label">User Profile Sub Item 0</li>
                        <ul class="vs-items vs-hidden">
                            <li class="vs-item">User Profile Sub Item 0-1</li>
                            <li class="vs-item">User Profile Sub Item 0-2</li>
                        </ul>
                    </ul>
                    <li class="vs-item">User Profile Sub Item</li>
                </ul>
            </ul>
        </ul>
    </div>
    <div class="vs-nav-menu"><button type="button" class="vs-button default primary md min-w">Posts</button></div>
</nav>

In fire fox everything work good. But in chrome drop-down content is on top of drop-down button. My css class is like this:

.vs-navigation {
    &.default {
        @apply flex flex-row;

        &>.vs-nav-menu {
            @apply relative;

            &>.vs-button {
                @include space-inline(sm, false);
            }

            &>.vs-menu {
                @apply absolute;
            }
        }
    }
}

I try develop it by pure html for check my css styles. Everything worked good. Now, why this component with vue doesn't work?

chrome

fire-fox